[][src]Struct spirit::Spirit

pub struct Spirit<O = Empty, C = Empty> { /* 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 builder 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 or registers from within a callback, you'll get a deadlock.

Interface

A lot of the methods on this are provided through the Extensible trait. You want to bring that into scope (possibly with use spirit::prelude::*) and you want to have a look at the methods on that trait.

Examples

use spirit::{Empty, Spirit};
use spirit::prelude::*;

Spirit::<Empty, Empty>::new()
    .on_config(|_opts, _new_cfg| {
        // Adapt to new config here
    })
    .run(|_spirit| {
        // Application runs here
        Ok(())
    });

Implementations

impl<O, C> Spirit<O, C> where
    C: DeserializeOwned + Send + Sync,
    O: StructOpt
[src]

pub fn new() -> Builder<O, C> where
    C: Default
[src]

A constructor of the Builder with default initial config.

Before the application successfully loads the first config, there still needs to be something (passed, for example, to validation callbacks) This puts the default value in there.

pub fn with_initial_config(config: C) -> Builder<O, C>[src]

Similar to new, but with specific initial config value

pub fn cmd_opts(&self) -> &O[src]

Access the parsed command line.

This gives the access to the command line options structure. The content doesn't change (the command line is parsed just once) and it does not contain the options added by Spirit itself.

pub fn config(&self) -> Arc<C>[src]

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.

Examples

use spirit::{Empty, Spirit};
use spirit::prelude::*;

let app = Spirit::<Empty, Empty>::new()
    .build(false)
    .unwrap();

let spirit = app.spirit();

let old_config = spirit.config();

Notes

It is also possible to hook an external configuration storage into Spirit (or Builder) through the cfg_store extension.

pub fn config_reload(&self) -> Result<(), AnyError>[src]

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.
  • Configuration mutators are run and can modify the loaded configuration.
  • 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 as that would lead to a deadlock.

pub fn is_terminated(&self) -> bool[src]

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};
use spirit::prelude::*;

let app = Spirit::<Empty, Empty>::new()
    .build(false)
    .unwrap();

let spirit = app.spirit();

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

pub fn terminate(&self)[src]

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.

Note that it is still up to the rest of your application to terminate as a result of this.

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

pub fn join_bg_thread(&self)[src]

Waits for the background thread to terminate.

The background thread terminates after a call to terminate or after a termination signal has been received.

If the thread hasn't started or joined already, this returns right away.

Auto Trait Implementations

impl<O = Empty, C = Empty> !RefUnwindSafe for Spirit<O, C>

impl<O, C> Send for Spirit<O, C> where
    C: Send + Sync,
    O: Send

impl<O, C> Sync for Spirit<O, C> where
    C: Send + Sync,
    O: Sync

impl<O, C> Unpin for Spirit<O, C> where
    O: Unpin

impl<O = Empty, C = Empty> !UnwindSafe for Spirit<O, C>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> IntoResult<T> for T[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.