oxide_update_engine/lib.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5#![cfg_attr(doc_cfg, feature(doc_cfg))]
6// Setting html_root_url allows cross-crate readme links to resolve. This
7// line is updated by cargo-release.
8#![doc(html_root_url = "https://docs.rs/oxide-update-engine/0.1.0")]
9
10//! An engine for declaring and executing sequential update steps with
11//! serializable event streams.
12//!
13//! The `oxide-update-engine` crate provides the execution engine for
14//! running update steps.
15//!
16//! * For types-only consumers (e.g. API clients), see
17//! [`oxide-update-engine-types`](oxide_update_engine_types).
18//! * For code to display update engine events as a human-readable
19//! stream, see [`oxide-update-engine-display`](https://docs.rs/oxide-update-engine-display).
20//!
21//! # Examples
22//!
23//! A minimal engine that runs a single update step:
24//!
25//! ```
26//! use oxide_update_engine::{
27//! StepSuccess, UpdateEngine, channel,
28//! };
29//! use oxide_update_engine::types::spec::EngineSpec;
30//!
31//! // A EngineSpec defines the domain-specific types that flow
32//! // through the engine. Use () for metadata you don't need.
33//! enum MySpec {}
34//! impl EngineSpec for MySpec {
35//! fn spec_name() -> String {
36//! "example".into()
37//! }
38//! type Component = String;
39//! type StepId = usize;
40//! type StepMetadata = ();
41//! type ProgressMetadata = ();
42//! type CompletionMetadata = ();
43//! type SkippedMetadata = ();
44//! type Error = anyhow::Error;
45//! }
46//!
47//! # #[tokio::main]
48//! # async fn main() -> anyhow::Result<()> {
49//! let log =
50//! slog::Logger::root(slog::Discard, slog::o!());
51//! let (sender, _receiver) = channel::<MySpec>();
52//! let engine = UpdateEngine::new(&log, sender);
53//!
54//! // Steps run sequentially in registration order.
55//! engine
56//! .new_step(
57//! "fw".to_owned(),
58//! 1,
59//! "Write firmware image",
60//! |_cx| async {
61//! // ... perform update work here ...
62//! StepSuccess::new(()).into()
63//! },
64//! )
65//! .register();
66//!
67//! engine.execute().await?;
68//! # Ok(())
69//! # }
70//! ```
71//!
72//! For more complex engines, including engines that have nested local and
73//! remote steps, see [the full
74//! example](https://github.com/oxidecomputer/oxide-update-engine/blob/main/e2e-example/src/main.rs).
75
76mod context;
77mod engine;
78mod errors;
79mod macros;
80
81pub(crate) use context::StepContextPayload;
82pub use context::{
83 CompletionContext, MetadataContext, SharedStepHandle, StepContext,
84 StepHandle, StepHandleToken,
85};
86pub use engine::{
87 AbortHandle, AbortWaiter, ComponentRegistrar, ExecutionHandle, NewStep,
88 StepResult, StepSkipped, StepSuccess, StepWarning, UpdateEngine, channel,
89};
90pub use errors::ExecutionError;
91pub use oxide_update_engine_types as types;