Expand description
The main manipulation handle/struct of the library.
This gives access to the runtime control over the behaviour of the spirit library and allows accessing current configuration and manipulate the behaviour to some extent.
Note that the functionality of the library is not disturbed by dropping this, you simply lose the ability to control the library.
By creating this (with the build pattern), you start a background thread that keeps track of signals, reloading configuration and other bookkeeping work.
The passed callbacks are run in the service threads if they are caused by the signals. They, however, can be run in any other thread when the controlled actions are invoked manually.
This is supposed to be a singleton (it is not enforced, but having more of them around is probably not what you want).
Warning
Only one callback is allowed to run at any given time. This makes it easier to write the callbacks (eg. transitioning between configurations at runtime), but if you ever invoke a method that contains callbacks from within a callback, you’ll get a deadlock.
Examples
use spirit::{Empty, Spirit};
Spirit::<Empty, Empty>::new()
.on_config(|_opts, _new_cfg| {
// Adapt to new config here
})
.run(|_spirit| {
// Application runs here
Ok(())
});
Implementations§
source§impl<O, C> Spirit<O, C>where
C: DeserializeOwned + Send + Sync,
O: StructOpt,
impl<O, C> Spirit<O, C>where
C: DeserializeOwned + Send + Sync,
O: StructOpt,
sourcepub fn with_initial_config(config: C) -> Builder<O, C>
pub fn with_initial_config(config: C) -> Builder<O, C>
Similar to new
, but with specific initial config value
sourcepub fn cmd_opts(&self) -> &O
pub fn cmd_opts(&self) -> &O
Access the parsed command line.
This gives the access to the type declared when creating Spirit
. The content doesn’t
change (the command line is parsed just once) and it does not contain the options added by
Spirit itself.
sourcepub fn config(&self) -> Lease<Arc<C>>
pub fn config(&self) -> Lease<Arc<C>>
Access to the current configuration.
This returns the current version of configuration. Note that you can keep hold of this snapshot of configuration (which does not change), but calling this again might give a different config.
If you do want to hold onto the returned configuration for longer time, upgrade the
returned Lease
to Arc
.
Examples
extern crate arc_swap;
extern crate spirit;
use arc_swap::Lease;
use spirit::{Empty, Spirit};
let (spirit, _, _) = Spirit::<Empty, Empty>::new()
.build(false)
.unwrap();
let old_config = Lease::upgrade(&spirit.config());
Notes
If created with the with_config_storage
, the current
configuration is also available through that storage. This allows, for example, having the
configuration in a global variable, for example.
sourcepub fn config_reload(&self) -> Result<(), Error>
pub fn config_reload(&self) -> Result<(), Error>
Force reload of configuration.
The configuration gets reloaded either when the process receives SIGHUP
or when this
method is called manually.
This is what happens:
- The configuration is loaded from all places.
- Validation callbacks are called (all of them).
- If no validation callback returns an error, success callbacks of the validation results are called. Otherwise, abort callbacks are called.
- Logging is reopened in the new form.
- The configuration is published into the storage.
- The
on_config
callbacks are called.
If any step fails, it is aborted and the old configuration is preserved.
Warning
The Spirit allows to run only one callback at a time (even from multiple threads), to make
reasoning about configuration transitions and such easier (and to make sure the callbacks
don’t have to by Sync
). That, however, means that you can’t call config_reload
or
terminate
from any callback (that would lead to a deadlock).
sourcepub fn is_terminated(&self) -> bool
pub fn is_terminated(&self) -> bool
Is the application in the shutdown phase?
This can be used if the daemon does some kind of periodic work, every loop it can check if the application should shut down.
The other option is to hook into on_terminate
and shut things down (like drop some futures and make the tokio event loop empty).
Examples
use std::thread;
use std::time::Duration;
use spirit::{Empty, Spirit};
let (spirit, _, _) = Spirit::<Empty, Empty>::new()
.build(false)
.unwrap();
while !spirit.is_terminated() {
thread::sleep(Duration::from_millis(100));
}
sourcepub fn terminate(&self)
pub fn terminate(&self)
Terminate the application in a graceful manner.
The Spirit/application can be terminated either by one of termination signals (SIGTERM
,
SIGQUIT
, SIGINT
) or by manually calling this method.
The termination does this:
- Calls the
on_terminate
callbacks. - Sets the
is_terminated
flag is set. - Drops all callbacks from spirit. This allows destruction/termination of parts of program by dropping remote handles or similar things.
- The background thread terminates.
Warning
The Spirit guarantees only one callback runs at a time. That means you can’t call this from within a callback (it would lead to deadlock).