This document describes how to use the C++ cloud config API. We are assuming you have created a config definition file (def file), which is the schema for one of your configs. Developing with the C++ Cloud Config API requires you to
In my example application, I have the following hierarchy related to config:
src/config-defs/motd.defGenerate code while standing in the
src/
folder:
$ make-config.pl $(pwd) $(pwd)/config-defs/motd.def
This will generate a config-defs/config-motd.h and config-defs/config-motd.cpp. These classes are immutable pure data objects that you can use to configure your application. The objects may be copied. In this example, the class MotdConfig is the generated config object.
To retrieve the config in your application, create a ConfigSubscriber.
A ConfigSubscriber is capable of subscribing to one or more configs.
The subscribe method takes an optional parameter as well, a timeout.
If the ConfigSubscriber was unable to subscribe within the timeout,
it will throw a ConfigRuntimeException.
To use the API, you must include the header of the generated classes
as well as the header shown in the example below.
The config API resides in the config
namespace:
Note that a ConfigSubscriber is NOT thread safe. It is up to the API user to ensure that the ConfigSubscriber is not used by multiple threads.
Once you have subscribed to all the configs you need, you may invoke the nextConfig() call on the ConfigSubscriber:
s.nextConfig(1000);
Given N subscriptions, the nextConfig call will wait up to 1 second for 1 to N configs to change. If they have changed, it returns true. If not, it returns false. See config API guidelines for a more advanced usage of the ConfigSubscriber.
Having called nextConfig(), the ConfigHandle can be asked for the current config:
This will retrieve the currently available config. If the subscribe calls succeeded and valid configs was returned by the config server, you are guaranteed that it will give you a correct config. For getting updates, thenextConfig
method can be used like:
The method ensures that whatever getConfig() returns next will be the latest config available. nextConfig has a timeout parameter, and will return false if timeout was reached, or true if a new generation of configs was deployed, and at least 1 of them changed.
When subscribing to multiple configs, a natural use case is to check which of the configs changed.
Therefore, the ConfigHandle class also contains a isChanged
method.
This method returns true if the previous call to nextConfig() resulted in a change, false if not.
The ConfigSubscriber constructor may also be passed a ConfigContext
object.
A context can be used to share resources with multiple ConfigSubscriber objects
and select the config source.
The context is passed a SourceSpec
parameter, which specifies the source of the config.
The different spec types are:
ServerSpec
, the default specConfigSet
, used for subscribing to a set of config objectsDirSpec
, used for subscribing to config files in a directoryFileSpec
, used for subscribing to a single fileRawSpec
, used for subscribing to a config value specified directlyMost users will use the default ServerSpec, or ConfigSet.
To help with unit testing, each config type has a corresponding builder type.
For instance, given FooConfig and BarConfig
generated config classes,
FooConfigBuilder and BarConfigBuilder
should also be available as mutable versions.
The builders can then be added to a ConfigSet
:
ConfigSet set; FooConfigBuilder fooBuilder; BarConfigBuilder barBuilder; set.addBuilder("id1", &fooBuilder); set.addBuilder("id1", &barBuilder); fooBuilder.foobar = 13; barBuilder.barfoo = 12;Having populated the set and set values on the builders, one must create a context containing the set:
IConfigContext::SP ctx(new ConfigContext(set));Once the context is created, it can be passed to the ConfigSubscriber: Once having subscribed, nextConfig and nextGeneration methods will work as normal. If you need to update a field to test reload, you can change the field of one of the builders and call reload on the context:
subscriber.nextConfig() // should return false if called before fooBuilder.foobar = 188; ctx->reload(); subscriber.nextConfig() // should return true now
How the config id relates to the application package deployed is covered in the main Config API document.
We also provide some helper classes such as the ConfigGetter
to test the config itself.
All config objects can be printed, and the API supports several ways of doing so.
To print config, you need to include <config/print.h>.
Config can be printed with any class implementing the ConfigWriter
interface.
A ConfigWriter
has a write method that takes any config class as input,
and writes it somewhere.
The following classes are provided:
FileConfigWriter
- Can write a config to a fileOstreamConfigWriter
- Can write a config to a C++ ostreamConfigWriter
also supports another parameter in the write method,
a ConfigFormatter
. Currently, we provide two formatters:
FileConfigFormatter
- Formats the config as the old
config payload format. This is the default formatterJsonConfigFormatter
- Formats the config as JSON
The FileConfigFormatter
is the default formatter if none is specified.
Example: Writing the config MyConfig
to a file as JSON:
MyConfig foo; FileConfigWriter writer("myfile.json"); writer.write(foo, JsonConfigFormatter());