lifeline/
lib.rs

1//! Lifeline is a dependency injection library for message-based applications.  Lifeline produces applications which are:
2//! - **Clean:** Bus implementations provide a high-level overview of the application, and services clearly define the messages they send and receive.
3//! - **Decoupled:** Services and tasks have no dependency on their peers, as they only depend on the message types they are sending or receiving.
4//! - **Stoppable:** Services and tasks are trivially cancellable.  For example, you can terminate all tasks associated with a connection when a client disconnects.
5//! - **Greppable:** The impact/reach of a message can be easily understood by searching for the type in the source code.
6//! - **Testable:**  Lifeline applications communicate via messages, which makes unit testing easy.  Spawn the service, send a message, and expect a received message.
7//!
8//! In order to achieve these goals, lifeline provides patterns, traits, and implementations:
9//! - The [Bus](./trait.Bus.html), which constructs & distributes channel Senders/Receivers, and Resources.
10//! - The [Carrier](./trait.CarryFrom.html), which translates messages between two Bus instances.  Carriers are critical when building large applications, and help minimize the complexity of the messages on each bus.
11//! - The [Service](./trait.Service.html), which takes channels from the bus, and spawns tasks which send and receive messages.
12//! - The [Task](./trait.Task.html), an async future which returns a lifeline when spawned. When the lifeline is dropped, the future is immedately cancelled.
13//! - The [Resource](./trait.Resource.html), a struct which can be stored in the bus, and taken (or cloned) when services spawn.
14//!
15//! For a quick introduction, see the [hello.rs example.](https://github.com/austinjones/lifeline-rs/blob/master/examples/hello.rs)
16//! For a full-scale application see [tab-rs.](https://github.com/austinjones/tab-rs)
17//!
18//! ## Quickstart
19//! Lifeline can be used with the [tokio](https://docs.rs/tokio/) and [async-std](https://docs.rs/async-std/) runtimes.  By default, lifeline uses `tokio`.
20//! ```toml
21//! lifeline = "0.6"
22//! ```
23//!
24//! [async-std](https://docs.rs/async-std/) can be enabled with the `async-std-executor` feature.  And the `mpsc` implementation can be enabled with the `async-std-channels` feature:
25//! ```toml
26//! lifeline = { version = "0.6", default-features = false, features = ["dyn-bus", "async-std-executor", "async-std-channels"] }
27//! ```
28//!
29//! Lifeline also supports [postage channels](https://docs.rs/postage/), a library that provides a portable set of channel implementations (compatible with any executor).
30//! Postage also provides Stream and Sink combinators (similar to futures StreamExt), that are optimized for async channels.  
31//! Postage is intended to replace the LifelineSender/LifelineReceiver wrappers that were removed in lifeline v0.6.0.
32//!
33//! ## Upgrading
34//! v0.6.0 contains several breaking changes:
35//! - The LifelineSender and LifelineReceiver wrappers were removed.  This was necessary due to the recent changes in the Stream ecosystem, and the upcoming stabilization of the Stream RFC.
36//! If you need Stream/Sink combinators, take a look at [postage](https://crates.io/crates/postage), or [tokio-stream](https://crates.io/crates/tokio-stream).
37//! - The barrier channel was removed.  It can be replaced with [postage::barrier](https://docs.rs/postage/0.3.1/postage/barrier/index.html).
38//! - The subscription channel was removed.  If you need it back, you can find the code before the removal [here](https://github.com/austinjones/lifeline-rs/blob/b15ab2342abcfa9c553d403cb58d2403531bf89c/src/channel/subscription.rs).
39//! - The Sender and Receiver traits were removed from prelude.   This is so that importing the lifeline prelude does not conflict with Sink/Stream traits.  You can import them with:
40//! `use lifeline::{Sender, Receiver}`.
41//!
42//! ## The Bus
43//! The [Bus](./trait.Bus.html) carries channels and resources, and allows you to write loosely coupled [Service](./trait.Service.html) implementations which communicate over messages.
44//!
45//! Channels can be taken from the bus. If the channel endpoint is clonable, it will remain available for other services.  
46//! If the channel is not clonable, future calls will receive an `Err` value. The Rx/Tx type parameters are type-safe,
47//! and will produce a compile error if you attempt to take a channel for an message type which the bus does not carry.
48//!
49//! Lifeline provides a [lifeline_bus!](macro.lifeline_bus.html) macro which stores channels and resources in `Box<dyn>` slots:
50//! ```
51//! use lifeline::lifeline_bus;
52//! lifeline_bus!(pub struct MainBus);
53//! ```
54//!
55//! ## The Carrier
56//! [Carriers](./trait.CarryFrom.html) provide a way to move messages between busses. [Carriers](./trait.CarryFrom.html) can translate, ignore, or collect information,
57//! providing each bus with the messages that it needs.
58//!
59//! Large applications have a tree of Busses. This is good, it breaks your app into small chunks.
60//! ```text
61//! - MainBus
62//!   | ConnectionListenerBus
63//!   |  | ConnectionBus
64//!   | DomainSpecificBus
65//!   |  | ...
66//! ```
67//! [Carriers](./trait.CarryFrom.html) allow each bus to define messages that minimally represent the information it's services need to function, and prevent an explosion of messages which are copied to all busses.
68//!
69//! [Carriers](./trait.CarryFrom.html) centralize the communication between busses, making large applications easier to reason about.
70//!
71//! ## The Service
72//! The [Service](./trait.Service.html) synchronously takes channels from the [Bus](./trait.Bus.html), and spawns a tree of async tasks (which send & receive messages).
73//! When spawned, the service returns one or more [Lifeline](./struct.Lifeline.html) values.  When a [Lifeline](./struct.Lifeline.html) is dropped, the associated task is immediately cancelled.
74//!
75//! It's common for [Service::spawn](./trait.Service.html#tymethod.spawn) to return a Result.  Taking channel endpoints is a fallible operation.  Depending on the channel type, the endpoint may not be clonable.
76//! Lifeline clones endpoints when it can (e.g. for `mpsc::Sender`, `broadcast::*`, and `watch::Receiver`).  Other endpoints are taken, removed, and future calls will return an Err.
77//!
78//! [Service::spawn](./trait.Service.html#tymethod.spawn) takes channels from the bus synchronously, which makes errors occur predictably and early. If you get an Err on an `mpsc::Receiver`,
79//! change it's binding in the bus to `broadcast::Sender`.
80//!
81//! ## The Task
82//! The [Task](./trait.Task.html) executes an Future, and returns a [Lifeline](./struct.Lifeline.html) when spawned.  When the lifeline is dropped, the future is immediately cancelled.
83//!
84//! [Task](./trait.Task.html) trait is implemented for all types - you can import it and use `Self::task` in any type.  In lifeline, it's
85//! most commonly used in Service implementations.
86//!
87//! ## The Resource
88//! [Resources](./trait.Resource.html) can be stored on the bus. This is very useful for configuration (e.g MainConfig), or connections (e.g. a TcpStream).
89//!
90//! [Resources](./trait.Resource.html) implement the [Storage](./trait.Storage.html) trait, which is easy with the [impl_storage_clone!](./macro.impl_storage_clone.html) and [impl_storage_take!](./macro.impl_storage_take.html) macros.
91
92mod bus;
93mod channel;
94
95#[cfg(feature = "dyn-bus")]
96pub mod dyn_bus;
97
98pub mod error;
99pub mod prelude;
100
101#[cfg(feature = "tokio-channels")]
102pub mod request;
103
104mod service;
105mod spawn;
106mod storage;
107
108// TODO: try to get this as cfg(test)
109pub mod test;
110
111pub use bus::*;
112pub use channel::lifeline::{Receiver, Sender};
113
114pub use channel::Channel;
115pub use service::*;
116pub use storage::Storage;
117pub use storage::*;
118
119pub use spawn::Lifeline;