Daemon interface

A daemon is the source of authority for one or more mKTL items; when a client gets or sets an item value, that request is handled by the daemon. Exactly how that request gets handled is entirely up to the daemon code; there are no restrictions imposed by the mKTL protocol itself, it is up to the daemon to resolve any consistency issues or conflicting requests.

The default behavior of the Store is to act as a caching key/value store: values come in, values go out, they may or may not persist across restarts depending on the configuration. This behavior is rarely sufficient for an application; a typical daemon will implement custom code behind the getting and setting of individual items. The Python interface described here expects the user to create custom subclasses of Store, which in turn may instantiate custom subclasses of Item. Background threads are used widely, polling and callbacks in particular are two areas where dedicated per-item background threads will invoke any/all registered methods; the author of any custom code should not assume that calls arriving via these mechanisms will be serialized or thread-safe to any meaningful degree.

Daemon.Store class

The Store class is the entry point and overall organization for the daemon; while it provides a common storage location for daemon-wide functions, such as handling requests and publishing broadcasts, from the perspective of the developer the Store is a container for the Item instances that define the actual behavior of the system. An incoming request, for example, is not handled by the Store, it is passed to the appropriate Item instance for proper handling.

The Store also defines the initialization sequence, if any, for the daemon: which steps to take upon startup, which Item subclasses to invoke for specific items, whether other initialization steps must occur such as defining a common communication point to access a hardware controller, or whether the initial state of a set of items needs to be manipulated before proceeding with routine operations.

In nearly all cases the developer will need to create a custom Store subclass to satisfy the operational goals of an individual daemon.

Daemon.Item class

The bulk of any daemon-specific logic will occur in Item subclasses. This is where requests get handled, where data gets interpreted, where logic is defined that could span items within and without the boundaries of the containing Store instance.

Subclass definitions of the Item.req_refresh(), Item.req_set(), and Item.validate() methods are especially important for defining any custom behavior. Any method with a req_ prefix is part of the handling chain for an inbound request, with :func`Item.req_get` and Item.req_set() implementing entry points for their respective operations, though if necessary Item.req_get() calls Item.req_refresh() in order to acquire the most recent value.

markd executable

The markd executable provides a command-line interface to invoke a persistent daemon executing a Store subclass as described above. It is the natural starting point for any persistent daemon implementing the scheme described in this document, since that is the precise purpose it is written for.

Refer to the section covering markd in the Executables documentation for additional details.