crius/lib.rs
1//! This module is the user-facing entrypoint for circuit breaker
2//! usage. The internal structures are available via other modules if
3//! required, but are (for now) mostly undocumented.
4//!
5//! You should usually stick to this module for documentation and
6//! examples.
7//!
8//! **Note**: The type aliases used by this public API require users
9//! to supply [function pointers][] instead of closures. This is
10//! because the type of a closure can not currently be named and
11//! circuit breakers will often have to be stored in context structs
12//! and the like without propagating the closure trait constraints all
13//! the way up.
14//!
15//! If you need to store closures or other types that implement the
16//! `Fn`-trait, please take a look at the internal modules.
17//!
18//! [function pointers]: https://doc.rust-lang.org/book/second-edition/ch19-05-advanced-functions-and-closures.html#function-pointers
19
20mod circuit_breaker;
21mod circuit_breaker_stats;
22mod window;
23
24pub mod command;
25pub mod error;
26
27pub use command::Config;
28pub use error::CriusError;
29
30/// Convenience type alias for function pointers matching the
31/// input/output and error types of a circuit breaker.
32pub type CommandFn<I, O, E> = fn(I) -> Result<O, E>;
33
34/// Convenience type alias matching the fallback function pointer of a
35/// circuit breaker.
36pub type FallbackFn<O, E> = fn(E) -> O;
37
38/// A Command is a runnable circuit breaker. It can be constructed
39/// either with or without a fallback method that can provide
40/// alternative values if the contained calls fail or if the breaker
41/// is open.
42///
43/// # Type parameters:
44///
45/// * `I`: *Input* type to the breaker's function.
46/// * `O`: *Output* type of the breaker's function.
47/// * `E`: *Error* type returned by the breaker's function. This type
48/// must implement `From<CriusError>` to propagate internal circuit
49/// breaker errors.
50pub type Command<I, O, E> = command::Command<I, O, E, CommandFn<I, O, E>, FallbackFn<O, E>>;
51
52/// Use this function to construct a circuit breaker *without* a
53/// fallback function.
54///
55/// # Example:
56///
57/// ```
58/// # use crius::{command, Config, CriusError};
59/// # #[derive(PartialEq, Debug)]
60/// # struct ExampleError;
61/// # impl From<CriusError> for ExampleError {
62/// # fn from(_: CriusError) -> Self { ExampleError }
63/// # }
64///
65/// // Define a simple circuit breaker command:
66/// let mut cmd = command(Config::default(), |n| {
67/// if n > 10 {
68/// Err(ExampleError)
69/// } else {
70/// Ok(n * 2)
71/// }}).unwrap();
72///
73/// // and run it with an example input:
74/// let result = cmd.run(10);
75/// assert_eq!(Ok(20), result)
76/// ```
77pub fn command<I, O, E>(
78 config: Config,
79 function: CommandFn<I, O, E>,
80) -> Result<Command<I, O, E>, CriusError>
81where
82 E: From<CriusError>,
83{
84 command::Command::define(config, function)
85}
86
87/// Use this function to construct a circuit breaker *with* a fallback
88/// function:
89/// # Example:
90///
91/// ```
92/// # use crius::{command_with_fallback, Config, CriusError};
93/// # #[derive(PartialEq, Debug)]
94/// # struct ExampleError;
95/// # impl From<CriusError> for ExampleError {
96/// # fn from(_: CriusError) -> Self { ExampleError }
97/// # }
98/// # let double_if_lt_ten = |n| if n > 10 {
99/// # Err(ExampleError)
100/// # } else {
101/// # Ok(n * 2)
102/// # };
103/// #
104/// // Define a simple circuit breaker command:
105/// let mut cmd = command_with_fallback(
106/// Config::default(),
107///
108/// // Same function as in the `command`-example
109/// double_if_lt_ten,
110///
111/// // Define a fallback:
112/// |_err| 4, // It's always four.
113/// ).unwrap();
114///
115/// // and run it with an example input:
116/// let result = cmd.run(11);
117/// assert_eq!(Ok(4), result)
118/// ```
119pub fn command_with_fallback<I, O, E>(
120 config: Config,
121 function: CommandFn<I, O, E>,
122 fallback: FallbackFn<O, E>,
123) -> Result<Command<I, O, E>, CriusError>
124where
125 E: From<CriusError>,
126{
127 command::Command::define_with_fallback(config, function, fallback)
128}