Struct spirit::Spirit[][src]

pub struct Spirit<S, O = Empty, C = Empty> where
    S: Borrow<ArcSwap<C>> + 'static, 
{ /* fields omitted */ }

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, _>::new(Empty {})
    .on_config(|_new_cfg| {
        // Adapt to new config here
    })
    .run(|_spirit| {
        // Application runs here
        Ok(())
    });

Methods

impl<O, C> Spirit<Arc<ArcSwap<C>>, O, C> where
    C: Deserialize<'de> + Send + Sync + 'static,
    O: StructOpt
[src]

A constructor for spirit with only inner-accessible configuration.

With this constructor, you can look into the current configuration by calling the `config', but it doesn't store it into a globally accessible storage.

Examples

use spirit::{Empty, Spirit};

Spirit::<_, Empty, _>::new(Empty {})
    .run(|spirit| {
        println!("The config is: {:?}", spirit.config());
        Ok(())
    });

impl<S, O, C> Spirit<S, O, C> where
    S: Borrow<ArcSwap<C>> + Send + Sync + 'static,
    C: Deserialize<'de> + Send + Sync,
    O: StructOpt
[src]

A constructor with specifying external config storage.

This way the spirit keeps the current config in the provided storage, so it is accessible from outside as well as through the config method.

Important traits for &'a mut R

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.

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, _>::new(Empty {})
    .build()
    .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.

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).

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, _>::new(Empty {})
    .build()
    .unwrap();

while !spirit.is_terminated() {
    thread::sleep(Duration::from_millis(100));
}

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).

Auto Trait Implementations

impl<S, O, C> Send for Spirit<S, O, C> where
    O: Send,
    S: Send

impl<S, O, C> Sync for Spirit<S, O, C> where
    O: Sync,
    S: Sync