Crate spirit_tokio[−][src]
Expand description
Support for tokio inside spirit
This provides configuration of the tokio runtime and installer of futures.
It also provides few configuration Fragment
s for configuring network primitives.
Note that this enables several features of tokio
.
Features
rt-from-cfg
: Allows creating runtime from configuration. Enables theTokio::FromCfg
variant andConfig
. Enabled by default.cfg-help
: Support for generating help for the configuration options.net
: Network primitive configurationFragment
s in thenet
module.stream
: Implementations of [tokio_stream::Stream
] on several types.futures
: Support for converting betweenfutures
’s and ourEither
.either
: Support for converting between ourEither
and the one from theeither
crate.
Examples
use std::future::Future;
use std::pin::Pin;
use std::time::Duration;
use err_context::AnyError;
use serde::{Deserialize, Serialize};
use spirit::{Empty, Pipeline, Spirit};
use spirit::prelude::*;
use spirit::fragment::driver::CacheEq;
use spirit_tokio::{FutureInstaller, Tokio};
use spirit_tokio::runtime::Config as TokioCfg;
use structdoc::StructDoc;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, StructDoc)]
#[serde(default)]
struct MsgCfg {
/// A message to print now and then.
msg: String,
/// Time between printing the message.
interval: Duration,
}
impl MsgCfg {
async fn run(self) {
loop {
println!("{}", self.msg);
tokio::time::sleep(self.interval).await;
}
}
}
impl Default for MsgCfg {
fn default() -> Self {
MsgCfg {
msg: "Hello".to_owned(),
interval: Duration::from_secs(1),
}
}
}
spirit::simple_fragment! {
impl Fragment for MsgCfg {
type Driver = CacheEq<MsgCfg>;
type Resource = Pin<Box<dyn Future<Output = ()> + Send>>;
type Installer = FutureInstaller;
fn create(&self, _: &'static str) -> Result<Self::Resource, AnyError> {
let fut = self.clone().run();
Ok(Box::pin(fut))
}
}
}
/// An application.
#[derive(Default, Deserialize, Serialize, StructDoc)]
struct AppConfig {
#[serde(flatten)]
msg: MsgCfg,
/// Configuration of the asynchronous tokio runtime.
#[serde(default)]
threadpool: TokioCfg,
}
impl AppConfig {
fn threadpool(&self) -> TokioCfg {
self.threadpool.clone()
}
fn msg(&self) -> &MsgCfg {
&self.msg
}
}
fn main() {
Spirit::<Empty, AppConfig>::new()
// Makes sure we have a runtime configured from the config.
// If we don't do this, the pipeline below would insert a default Tokio runtime to make
// it work. If you want to customize the runtime (like here), make sure to insert it
// before any pipelines requiring it (otherwise you get the default one from them).
.with_singleton(Tokio::from_cfg(AppConfig::threadpool))
// Will install and possibly cancel and replace the future if the config changes.
.with(Pipeline::new("Msg").extract_cfg(AppConfig::msg))
// Just an empty body here.
.run(|spirit| {
// Usually, one would terminate by CTRL+C, but we terminate from here to make sure
// the example finishes.
spirit.terminate();
Ok(())
})
}
An alternative approach can be seen at handlers::ToFutureUnconfigured
.
Re-exports
pub use crate::installer::FutureInstaller;
pub use crate::net::TcpListen;
pub use crate::net::TcpListenWithLimits;
pub use crate::net::UdpListen;
pub use crate::runtime::Tokio;