Last time we looked at autobindings we mentioned that one of the next steps was introducing support for Application-level experiments. In this development log we will explore what application-level experiments are (technically), and how we added (optional) autobindings support for them.
The Structure of an Application Experiment
An application-level experiment consists of:
- A set of top-level APIs, e.g.
CreateServer
,LoadServer
,DeleteServer
- these are the APIs that we want to expose to calling applications. - An encapsulating structure for the set of APIs, e.g.
ServersFunctionality
- it is much easy to manage a cohesive set of functionality if it is wrapped up in a single entity. - A global variable that exists at the top level of libCwtch, e.g.
var serverExperiment *servers.ServersFunctionality servers
- our single pointer to the underlying functionality. - A set of management-related APIs, e.g.
Init
,UpdateSettings
,OnACNEvent
- in the case of the server hosting experiment we need to perform specific actions when we start up (e.g. loading unencrypted hosted servers), and when settings are changed (e.g. if the server hosting experiment is disabled we need to tear down all active servers). - Management code within
_startCwtch
and_reconnectCwtch
that calls the management APIs on the global variable.
From a code generation perspective we already have most of the functionality is place to support (1) - the one major difference being that we need to wrap function calls on the global variable associated with the experiment, instead of on application
or a specific profile
.
Most of the effort required to support optional experiments was focused on optionally weaving experiment management code within the template.
New Required Management APIs
To achieve this weaving, we now require application-level experiments to implement an EventHandlerInterface
interface and expose itself via an initialize constructor Init(acn, appDir) -> EventHandlerInterface
, and Enable(app, acn)
.
For now this interface is rather minimal, and has been mapped almost exactly to how the server hosting experiment already worked. If, or when, a new application experiment is required we will likely revisit this interface.
We can then generate, and optionally include blocks of code like:
<experimentGlobal> = <experimentPackage>.Init(&globalACN, appDir)
eventHandler.AddModule(<experimentGlobal>)
<experimentGlobal>.Enable(application, &globalACN)
and place them at specific points in the code. EventHandler
has also been extended to maintain a collection of modules
so that it can pass on interesting events.
Adding Support for Application Experiments in the Spec File
We have introduced a new !
operator which can be used to gate APIs behind a configured experiment. Along with a new templating option exp
which will call the function on the configured experiment, and global
to allow the setting up of a global functionality within the library.
# Server Hosting Experiment
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
!serverExperiment global serverExperiment *servers.ServersFunctionality servers
!serverExperiment exp CreateServer application password string:description bool:autostart
!serverExperiment exp SetServerAttribute application string:handle string:key string:val
!serverExperiment exp LoadServers application acn password
!serverExperiment exp LaunchServers application acn
!serverExperiment exp LaunchServer application string:handle
!serverExperiment exp StopServer application string:handle
!serverExperiment exp StopServers application
!serverExperiment exp DestroyServers
!serverExperiment exp DeleteServer application string:handle password
Generation-Time Inclusion
Without any arguments provided generate-bindings
will not generate code for any experiments.
In order to determine what experimental code to generate, generate-bindings
now interprets arguments as enabled compile time experiments, e.g. generate-bindings serverExperiment
will turn on generation of server hosting code, per the spec file above.
Cwtch UI Integration
The UI, and other downstream applications, can now check for support for server hosting by simply checking if the loaded library provides the expected symbols, e.g. c_LoadServers
- if it doesn't then the UI is safe to assume the feature is not available.
Nightlies & Next Steps
We are now publishing nightlies of autobinding derived libCwtch-go, along with Repliqate scripts for reproducibility.
With application experiments supported, this phase of autobindings comes to a close. The immediate next steps involve extensive testing and release candidates proving out the new bindings to ensure that no bugs have been introduced in the migration from libCwtch-go. These candidates will form the basis for Cwtch Beta 1.11.
However, there is still more work to do, and we expect to make progress on a few areas over the next few months, including:
- Dart Library generation: since we now have a formal description of the bindings interface, we can move ahead with also autogenerating the Dart side of the bindings interface, giving a boost to UI integration of new features, and allowing us to generate tailored versions of the UI interface, e.g. one compiled without experiment support. We can also extend the same logic to other downstream interfaces, e.g. libcwtch-rs.
- Documentation generation: as another benefit of a formal description of the bindings interface, we can easily generate documentation compatible with docs.cwtch.im.
Help us go further!
We couldn't do what we do without all the wonderful community support we get, from one-off donations to recurring support via Patreon.
If you want to see us move faster on some of these goals and are in a position to, please donate. If you happen to be at a company that wants to do more for the community and this aligns, please consider donating or sponsoring a developer.
Donations of $5 or more can opt to receive stickers as a thank-you gift!
For more information about donating to Open Privacy and claiming a thank you gift please visit the Open Privacy Donate page.