1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Steno is an in-progress prototype implementation of distributed sagas.
//! Sagas orchestrate the execution of a set of asynchronous tasks that can
//! fail.  The saga pattern provides useful semantics for unwinding the whole
//! operation when any task fails.  For more on distributed sagas, see [this
//! 2017 JOTB talk by Caitie McCaffrey][1].
//!
//! [1]: https://www.youtube.com/watch?v=0UTOLRTwOX0
//!
//! ## Overview
//!
//! * Write some functions that will be used as _actions_ and _undo actions_ for
//!   your saga.  Package these up with [`ActionFunc::new_action()`].
//! * Add these actions to an [`ActionRegistry`]
//! * Use [`DagBuilder`] to construct a graph of these actions.  Wrap this up in
//!   a [`SagaDag`].
//! * Construct a saga execution coordinator with [`sec()`] and use that to run
//!   the saga.  You can start with an [`InMemorySecStore`] or impl your own
//!   [`SecStore`].
//!
//! This crate is necessarily somewhat complex to use.  **For a detailed,
//! documented example, see examples/trip.rs.**

#![deny(elided_lifetimes_in_paths)]
// We disable the warning for unstable name collisions because we deliberately
// have some conflicts in rust_features.rs (corresponding to backports of
// unstable features).  If and when these features are stabilized, we should see
// warnings that our backported versions are unused and we can remove them.
#![allow(unstable_name_collisions)]

mod dag;
mod example_provision;
mod rust_features;
mod saga_action_error;
mod saga_action_func;
mod saga_action_generic;
mod saga_exec;
mod saga_log;
mod sec;
mod store;

// TODO-cleanup The example_provision stuff should probably be in a separate
// crate that depends on "steno".  That would ensure it only uses public
// interfaces.  However, the "steno" crate wants to have an example that uses
// this crate, hence our problem.
pub use example_provision::load_example_actions;
pub use example_provision::make_example_provision_dag;
pub use example_provision::ExampleContext;
pub use example_provision::ExampleParams;
pub use example_provision::ExampleSagaType;

pub use dag::ActionName;
pub use dag::ActionRegistry;
pub use dag::ActionRegistryError;
pub use dag::Dag;
pub use dag::DagBuilder;
pub use dag::DagBuilderError;
pub use dag::Node;
pub use dag::NodeName;
pub use dag::SagaDag;
pub use dag::SagaId;
pub use dag::SagaName;
pub use saga_action_error::ActionError;
pub use saga_action_error::UndoActionError;
pub use saga_action_func::new_action_noop_undo;
pub use saga_action_func::ActionFunc;
pub use saga_action_func::ActionFuncResult;
pub use saga_action_generic::Action;
pub use saga_action_generic::ActionData;
pub use saga_action_generic::ActionResult;
pub use saga_action_generic::SagaType;
pub use saga_action_generic::UndoResult;
pub use saga_exec::ActionContext;
pub use saga_exec::SagaExecStatus;
pub use saga_exec::SagaResult;
pub use saga_exec::SagaResultErr;
pub use saga_exec::SagaResultOk;
pub use saga_log::SagaLog;
pub use saga_log::SagaNodeEvent;
pub use saga_log::SagaNodeEventType;
pub use saga_log::SagaNodeId;
pub use sec::sec;
pub use sec::RepeatInjected;
pub use sec::SagaSerialized;
pub use sec::SagaStateView;
pub use sec::SagaView;
pub use sec::SecClient;
pub use store::InMemorySecStore;
pub use store::SagaCachedState;
pub use store::SagaCreateParams;
pub use store::SecStore;

// TODO-cleanup This ought not to be exposed.  It's here because we expose
// SagaTemplateGeneric, which is important, and it has a function that uses this
// type.  This ought to be a sealed trait where this function is private or
// something.
pub use sec::SecExecClient;

#[macro_use]
extern crate slog;
#[macro_use]
extern crate newtype_derive;