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
102
//! # TitanRt
//!
//! Model‑first, typed reactive runtime for real‑time systems.
//!
//! This crate focuses on **models that own connectors and streams**. The runtime
//! only orchestrates lifecycle (start/restart/hot‑reload/shutdown) and back‑pressure,
//! while your model pulls typed events from its streams and pushes typed actions back.
//!
//! **Read the full guide & architecture in the project README.**
//! – <https://crates.io/crates/titanrt>
//!
//! ## When to use
//! - You need a compact event loop with predictable back‑pressure.
//! - You want typed boundaries between model, I/O adapters and state.
//! - You care about graceful, hierarchical cancellation and optional core pinning.
//!
//! ## Core types (jump in)
//! - [`runtime::Runtime`] — control thread that feeds commands and drives the model.
//! - [`model::BaseModel`] — your app logic (owns connectors/streams).
//! - [`connector::BaseConnector`] — spawns typed worker **streams**.
//! - [`connector::Stream`] — handle with action TX, event RX, health, state and cancel.
//! - [`utils::CancelToken`] — hierarchical cooperative cancellation.
//!
//! ## Minimal model loop (owning a stream)
//! ```rust,ignore
//! use titanrt::model::{BaseModel, ExecutionResult, StopKind, StopState};
//! use titanrt::runtime::{Runtime, RuntimeConfig};
//! use titanrt::utils::CancelToken;
//! use titanrt::io::base::{NullTx};
//! use anyhow::Result;
//!
//! // Your connector implements StreamRunner + StreamSpawner; omitted here.
//! // struct EchoConnector { /* ... */ }
//! // impl BaseConnector for EchoConnector { /* ... */ }
//!
//! struct MyModel {
//! // connector: EchoConnector,
//! // echo: Stream<...>, echo_tx: ..., echo_rx: ...
//! }
//!
//! impl BaseModel for MyModel {
//! type Config = ();
//! type OutputTx = NullTx; // or your own transport
//! type Event = (); // events normally come from streams, not control plane
//! type Ctx = ();
//!
//! fn initialize(_: (), _: (), _: Option<usize>, _: NullTx, _cancel: CancelToken) -> Result<Self> {
//! // 1) Build connector(s) and spawn stream(s) here.
//! // 2) Keep action_tx, event_rx and state handles in the model.
//! Ok(Self{})
//! }
//!
//! fn execute(&mut self) -> ExecutionResult {
//! // Drain events from stream(s), push actions if needed, publish state snapshots.
//! // self.echo.try_recv().ok();
//! ExecutionResult::Relax
//! }
//!
//! fn on_event(&mut self, _e: Self::Event) {}
//!
//! fn stop(&mut self, _kind: StopKind) -> StopState {
//! // Cancel and join streams here.
//! StopState::Done
//! }
//! }
//!
//! fn main() -> Result<()> {
//! let cfg = RuntimeConfig {
//! init_model_on_start: true,
//! core_id: None,
//! max_inputs_pending: Some(1024),
//! max_inputs_drain: Some(64),
//! stop_model_timeout: Some(5),
//! };
//! let rt = Runtime::<MyModel>::spawn(cfg, (), (), NullTx)?;
//! rt.run_blocking()?;
//! Ok(())
//! }
//! ```
//!
//! ## Notes
//! - Prefer delivering data via **streams** (event plane inside the model).
//! Use the control plane for **commands** only.
//! - Pin to specific cores through stream descriptors and [`utils::CorePickPolicy`].
//! - See README for a full, compiling connector/stream example and real transports.
//!
//! ---
//! Re‑exports live under modules like `runtime`, `model`, `connector`, `io`, and `utils`.