Client interface
A client is any software component interacting with a daemon, in the form of issuing requests, receiving responses to requests, and receiving asynchronous updates of new item values. The Python interface described here makes liberal use of background threads, callbacks in particular can and will arrive from background threads as asynchronous updates arrive. 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.
Unlike the Daemon interface, a typical client application will not need subclasses of the classes defined here, they are expected to be used directly, as-is.
Getting started
mKTL will cache information locally; there are no restrictions on where this information gets cached, other than it needs to be cached somewhere. The default location for this cache is:
$HOME/.mKTL
You can override this location by setting the MKTL_HOME
environment
variable to the absolute path of your choice; any directory specified in
this fashion will be created if it does not already exist. Alternatively,
the program may invoke the mktl.home()
method to specify the location
at run time.
- mktl.home(default=None)
Return the directory location where we should be loading and/or saving configuration files. This defaults to
$HOME/.mKTL
, but can be overridden by calling this method with a valid path, or by setting theMKTL_HOME
environment variable. Note that changes to the environment variable will be ignored unless it is set prior calling this method.
The mktl.get()
method is the universal entry point to retrieve a
Store
or Item
instance; client configuration is automatically
refreshed if necessary, and the remainder of the connection logic is handled
by the Store
.
All other client operations, such as getting and setting item values, are
handled via the Item
instance.
- mktl.get(store, key=None)
The
get()
method is intended to be the primary entry point for all interactions with a key/value store.The return value is either a cached
Store
orItem
instance. If both a store and a key are specified, the requested item will be returned from the specified store. The same will occur if the sole argument is a store and key name concatenated with a dot (store.KEY). AStore
instance will be returned if the sole argument provided is a store name. Both the store and the key are case-insensitive.If the caller always uses
get()
to retrieve aStore
orItem
they will always receive the same instance of that class. In that sense,get()
is a factory method enforcing a singleton pattern.
The Store class
The Store
class is primarily an organizational structure, providing
a dictionary-style interface to retrieve Item
instances.
- class mktl.Store(name)
The
Store
implements a key/value store, effectively a Python dictionary with some additional context. A store has a unique name within the local mKTL context; which daemons will be contacted to handle further requests is determined on a per-Item basis, re-use of connections is managed in themktl.protocol
submodule, not here.
The Item class
The bulk of the client interactions will occur with the mktl.Item
class. In addition to the methods described here an mktl.Item
instance
can be used with Python operators, such as addition/concatenation or
multiplication.
The behavior of an mktl.Item
when used in this fashion will be aligned
with the native Python binary type for the item value; for example, if an
item test.BAR has an integer value 12, test.BAR + 5
will return 17; if
the value is instead the string value ‘12’, the same operation will raise a
TypeError exception.
- class mktl.Item(store, key, subscribe=True, authoritative=False, pub=None)
An Item represents a key/value pair, where the key is the name of the Item, and the value is whatever is provided by the authoritative daemon. The principal way for both clients and daemons to get or set the value is via the
value()
property.A non-authoritative Item will automatically
subscribe()
itself to any available updates.- get(refresh=False, formatted=False)
Retrieve the current value. Set refresh to True to prompt the daemon handling the request to provide the most up-to-date value available, potentially bypassing any local cache. Set formatted to True to receive the human-readable formatting of the value, if any such formatting is available.
- register(method)
Register a callback to be invoked whenever a new value is received, either by a direct
get()
request or the arrival of an asynchronous broadcast.subscribe()
will automatically be invoked as necessary, the client does not need to call it separately.
- set(new_value, wait=True)
Set a new value. Set wait to True to block until the request completes; this is the default behavior. If wait is set to False, the caller will be returned a
mktl.protocol.message.Request
instance, which has amktl.protocol.message.Request.wait()
method that can optionally be invoked block until completion of the request; the wait will return immediately once the request is satisfied. There is no return value for a blocking request; failed requests will raise exceptions.