Struct spirit::Spirit[][src]

pub struct Spirit<O = Empty, C = Empty> { /* fields omitted */ }
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 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

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.

Similar to new, but with specific initial config value

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.

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.

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.

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));
}

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

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

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

Turns self into the result.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.