[−][src]Module spirit::fragment
Fragments of configuration.
There are several crates that provide common fragments of configuration to configure some
specific functionality. These fragments are described in terms of the Fragment
trait.
How to use them
A Fragment
can be used directly, usually through create
method. The trait has some
other methods and associated types, but these are usually used only internally.
The other option is to use fragments through Pipeline
s. A pipeline describes how the
fragment is extracted from the configuration, how instances of resources it describes are
cached and created, how to post-process them and how to install or activate them. Depending on
the kind of fragment, less or more tweaking may be needed or desirable.
How pipelines work
A Pipeline
manages certain fragment of configuration and creates Resource
s out of it.
There are several traits in play there.
- A pipeline is triggered whenever new configuration is loaded. It runs its configured
Extractor
. This extractor provides an instance of theFragment
. - A
Driver
is provided with the extracted fragment. TheDriver
decides if theResource
needs to be recreated or if an old instance need to be destroyed. Each fragment has its defaultDriver
, but the driver of a pipeline can be manually replaced by other one, to for example change caching strategy. Note that theDriver
is allowed to partition theFragment
into smallerFragment
s and drive the rest of the pipeline multiple times on the smaller ones (eg. aVec<F>
would be split into multiple runs overF
). - When creating the
Resource
, there are two stages. First, aSeed
is created with themake_seed
method. Then one or moreResource
s are made out of theSeed
with themake_resource
method. This allows more flexible caching strategies and allows for example to change attached configuration without closing and opening a network socket if the port haven't changed (which would be problematic, as spirit first tries to create the new instance and only if it works gets rid of the old one ‒ but that couldn't be done if we still had the old with the same port). SomeFragment
s don't need this two-stage configuration, therefore they have theSeed
set to()
and trivialmake_seed
method. You can use thesimple_fragment
macro to generate such trait configuration. - Then the resource goes through configured set of
Transformation
s. These may be quite arbitrary, but they usually tie the resource with some kind of functionality ‒ a network socket is provided with a function to handle each new connection, a HTTP server is provided with the service it'll serve, etc. A freshly createdPipeline
has no transformations, but they can be added. - Finally, the resulting product is installed using the
Installer
. Some fragments come with a default installer, some do not. TheInstaller
is often set as part of a transformation. Nevertheless, an installer can always be set manually. - The installer returns
UninstallHandle
s. These represent the lifetime of the installed resources. The pipeline stores them until the time is right to destroy the resources ‒ then it drops the handles, which results in removal of the resources.
Names
Most methods around the mentioned traits take a name: &'static str
parameter. This is used by
them to enrich log messages, as there might be multiple distinct parts of configuration of the
same type.
The name is provided when creating the Pipeline
. It needs to be a string literal, but as
this should correspond to specific functionality in the program, this should not be very
limiting.
TODO: An example
How to create a fragment
First, try to do it manually, without fragments or pipeline ‒ eg. write the code that takes the configuration and creates something out of it and activates it.
Then decide how this should be reloaded when new configuration appears, how it can be reinstalled or if and how it should be cached.
Then you can have a look at available pieces, like ready-made
drivers or installers. Sometimes, they come from another trait ‒ eg.
the spirit_tokio
crate comes with an installer for futures. Usually, you need to implement
only the Fragment
trait (either in two-stage or single-stage fashion), but sometimes you
might need to add some kind of Transformation
to tie the part that comes from the
configuration with some actual code.
You may also want to implement the Stackable
and possibly Comparable
traits for the
fragment.
Modules
driver | |
pipeline | The home of the |
Structs
SeqInstaller | A sequence installer. |
Traits
Extractor | A trait describing something that extracts a fragment from configuration and command line options. |
Fragment | A fragment of configuration. |
Installer | An entity that is able to install a resource. |
Optional | A trait similar to |
Stackable | A trait to mark |
Transformation | A transformation of resources. |