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
// Project: hyperi-rustlib
// File: src/concurrency/mod.rs
// Purpose: Three generic async primitives for HyperI Rust libraries
// Language: Rust
//
// License: FSL-1.1-ALv2
// Copyright: (c) 2026 HYPERI PTY LIMITED
//! Async concurrency primitives.
//!
//! Three patterns, each generic over the consumer's domain type, each
//! the canonical way to do the corresponding shape of async work in
//! HyperI Rust libraries. See
//! `hyperi-ai/standards/languages/RUST.md` §"Three async primitives
//! every HyperI library uses" for design philosophy and a decision
//! matrix.
//!
//! # Decision matrix
//!
//! | Shape | Use |
//! |---|---|
//! | Consumer pushes; background batches + writes to a backend | [`BackgroundSink`] + [`SinkDrain`] |
//! | Timer-driven loop, no inbound queue | [`PeriodicWorker`] + [`PeriodicTask`] |
//! | Mutable state, command queue, optional oneshot replies | [`ActorHandle`] + [`Actor`] |
//!
//! # The hard rule
//!
//! **An `async fn` in HyperI libraries MUST yield to the runtime.**
//! No hidden synchronous I/O. If you need sync I/O from async:
//!
//! - Use `tokio::fs` / `tokio::io::AsyncWrite` for occasional async I/O.
//! - Use [`BackgroundSink`] for high-throughput durable writes.
//! - Use `tokio::task::spawn_blocking` for one-off unavoidable sync work.
//! - Don't — push the sync work to startup, before the runtime is hot.
//!
//! The grep-based `tests/sync_in_async.rs` lint enforces this
//! mechanically: any `async fn` body containing `std::fs::*`,
//! `std::io::Write::write_*`, `std::thread::sleep`, `reqwest::blocking::*`,
//! or `parking_lot::*::lock()` held across `.await` fails CI.
//!
//! # Considered alternatives
//!
//! - `tokio-actors` (v0.6) — covers `ActorHandle` + `PeriodicWorker`
//! cleanly but doesn't provide batched-drain-with-flush-barrier,
//! which is the load-bearing case for [`BackgroundSink`]. Wrapping
//! it would equal the size of this module's impl. Rejected.
//! - `tokio-prometheus-metered-channel` (v0.2) — bounded channel with
//! Prometheus metrics, no actor / batch / flush. Too narrow.
//! - `xtra`, `actix`, `bastion` — heavy actor frameworks. Don't fit
//! the sink shape. Rejected.
//! - `tracing-appender::non_blocking` — used elsewhere for the logger
//! subscriber; orthogonal to this module's tokio-runtime concerns.
//!
//! Rationale per [Alice Ryhl's "Actors with Tokio"](https://ryhl.io/blog/actors-with-tokio/)
//! and the [2026-05-08 audit](https://github.com/hyperi-io/hyperi-rustlib).
pub use ;
pub use ;
pub use ;
pub use ;