Tool of Thought

APL for the Practical Man

"You don't know how bad your design is until you write about it."

Revisiting Rumba

July 17, 2024

Rumba has been around a long time. Mostly it was written as an exercise to understand HTTP, but is has also proved quite useful for testing sites and applications that may be served by other means in production.

When Rumba was originally written, Dyalog's TCP toolkit Conga, on which Rumba is based, did not support HTTP directly. Much code in Rumba is devoted to parsing TCP messages to know where the header ends and the body starts, where chunks start and end, etc. Now Conga supports HTTP. Furthermore it supports WebSockets, which requires the new HTTP functionality. In addition Conga has made some improvements to the event handling that clean up some things. The need for Abacus to use WebSockets is the catalyst for updating Rumba to take advantage of all that Conga now has to offer.

Rather than jettisoning the original code, we have a new Rumba server property UseCongaHTTP which defaults to 0. Setting to 1 does the obvious, instructing Rumba to use Conga's HTTP mode. Being able run a Rumba server both ways is useful for testing.

The new code is, for now in a temporary branch, where it will probably remain for a few months.

Conga also now has features to fully parse the header and trailer. These features are not taken advantage of yet in Rumba, as we don't want to introduce too many changes at once. We are, however, taking advantage of the new Conga EventMode property to streamline code and get rid of some magic numbers that Conga used to produce.

Because Rumba is heavily threaded and written largely in dfns, it has to use some tradfn workarounds to avoid a long-standing bug in the interpreter. This bug is now fixed in Dyalog version 19, so we can eliminate the workarounds.

Taking advantage of Conga's HTTP mode while not substantially rewriting Rumba required certain decisions about threading. The current threading model may not be the best. In a future post we will review the threading model for Rumba, see how it was adapted to use Conga's HTTP mode, compare it to what Dyalog's Jarvis does, and see if there are any better alternatives.

Styles, Themes, and Layouts

July 2, 2024

For an Abacus application, we need a way to organize our CSS, apply themes, provide some default application layout and styling, and also let the programmer override everything.

An Abacus document (and any element) has a Style property which is a vector of CSS rules. For static documents, this property is generally set directly by the programmer. When a document represents an SPA built on Abacus components, we need to be able to assemble additional rules, and provide a way for the programmer to organize them. Two additional properties are provided to specify CSS rules: LayoutStyle and ApplicationStyle.

The LayoutStyle property contains CSS rules for top level layout. This might be something like the header, main and footer elements of the app.

For an SPA, the Style property of the root <html> element should not be set (it will be overridden if it is set). Abacus will automatically set this property, constructing it from the 'LayoutStyle and ApplicationStyle` properties, as well as the component library styles.

The order in which styles are applied is as follows:

  1. LayoutStyle (user provided, though Abacus should have a library of useful ones)
  2. Abacus Styles (provided by Abacus, including built-in component )
  3. ApplicationStyle (user provided)

In other words, the programmer can provide styles to be applied before and after the built in styles provided by Abacus. These groups of CSS rules are, in the end, arbitrary. I'm not even sure the programmer needs to be able specify rules before the Abacus rules, but certainly after. However I do think it is useful to split apart, for example, a rule that says the button radius should be 5px, from a rule that says the <body> element of the document should flex.

It should be possible to create an attractive application by simply specifying a layout provided by Abacus.

Abacus uses APL functions to construct CSS. We call these CSS functions. A CSS function takes a theme as its right argument. A theme is simply a namespace of names and values, defining colors, font names and size, and other parameters. It performs the same function as CSS custom properties.

Much or all of this will probably change.

A WebSocket Experiment

July 1, 2024

First, grab a coffee and spend 32 entertaining minutes with Theo.

Ok, now that you have enjoyed his sartorial stylings, lets talk about WebSockets and avoiding JavaScript.

We have been experimenting with WebSockets and the HTMLRenderer. The goal is to see if it is possible to build a highly interactive desktop app with almost no JavaScript, where every UI interaction is handled by APL. This appears to work, and be a viable approach. We have implemented a datagrid which is probably the most intensive user interaction case for a business app.

With the Abacus DataGrid, every single keystroke event is sent to the browser over a websocket. On each press of the down-cursor key, for examle, the event is sent to APL, which must determine if the grid should scroll, extract and prepare the data to display, render the HTML, send it back over the websocket to the client, which must then replace the innerHMTL of the table element. You can press and hold the cursor key and the datagrid will scroll as smooth and fast as an Excel user would expect. No latency. Awesome.

But we are on one machine. What would happen if we tried to run the datagrid in a web app? Over the internet. From a client in Rome to a server in Los Angeles? At the Carlisle Group 2024 Italy Moot, we tried just that. Amazingly there hardly appeared to be any difference. Scrolling appeared to be just as smooth and fast. I assume it had to be a little slower, we just couldn't really notice it. It was not a scientific test, we just just scrolled around and observed how the performance felt.

Next, we tried 3 connections/users in Rome to the same server in LA. What would happen if all 3 users tried to scroll around? Here we assumed the performance would degrade significantly. Asking a single APL server to handle a flood of keystroke events from multiple clients, where each requires not trivial processing, would be asking too much. We were not wrong, the performance degraded profoundly.

It remains to be seen what architectural options there are for heavily interactive single-user web apps in this model that require a lot of server power for each user. Maybe a different Docker container for each user, each with its own APL instance is viable, for a relatively small number users. Not sure how this would work, or even if it could, for a multi-user app if the users have their own APL instance.

For multiuser apps that do not require that much server power per user, the Abacus model of the client passing every event to APL via a WebSocket may turn out to be quite viable.

We'll see.

More posts...