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
//! The session aggregate: lifecycle, in-flight requests, cancellation, progress.
//!
//! # Everything here is a pure transition
//!
//! No clock, no runtime, no I/O. Time arrives as an [`Instant`] read from a
//! port the application layer owns; a request becomes in-flight because
//! [`RequestRegistry::register`] was called, and stops being in-flight because
//! something completed or cancelled it. That is the whole of the domain's
//! contribution, and keeping it to that is what makes the state machine
//! testable by a property test rather than by a mock.
//!
//! # The `std::sync` in [`cancellation`]
//!
//! [`cancellation::CancellationToken`] holds a `Mutex<Vec<Waker>>` and a
//! `OnceLock`, which is more machinery than a value object. It is here rather
//! than in `application` for one reason: the in-flight registry has to hold
//! the token, and a domain aggregate may not reach outward to borrow one. The
//! state it holds — *has this request been cancelled, and what did the peer
//! say* — is domain state; the waker list is the standard-library plumbing that
//! publishes it to whoever is awaiting. No `Waker` is invented by this crate,
//! and no executor is named: the token is polled by whoever waits on it, so it
//! works on any runtime, including a test's.
//!
//! # Why there is no timer
//!
//! The domain knows a request's *budget* and can say when it is spent, because
//! that is arithmetic over injected instants. What wakes a future when a
//! deadline passes belongs to the runtime, and the runtime belongs to the
//! transport adapter. The engine therefore computes expiry and the adapter
//! races it — the same division that keeps a transaction inside its adapter.
pub use Cancelled;
pub use ;
pub use ;
pub use ;
pub use ;