hyperi_rustlib/tiered_sink/mod.rs
1// Project: hyperi-rustlib
2// File: src/tiered_sink/mod.rs
3// Purpose: Tiered sink with disk spillover for resilient message delivery
4// Language: Rust
5//
6// License: BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Tiered sink with automatic disk spillover for resilient message delivery.
10//!
11//! This module provides a wrapper around any async sink (Kafka, S3, HTTP, etc.)
12//! that automatically spills messages to disk when the primary sink is unavailable
13//! or backpressuring, then drains them back when the sink recovers.
14//!
15//! ## Design
16//!
17//! ```text
18//! ┌─────────────────────────────────────┐
19//! │ TieredSink │
20//! │ │
21//! Message ────────►│ try_send() to primary sink │
22//! │ │ │
23//! │ ▼ │
24//! │ ┌─────────┐ │
25//! │ │ Success │──► Done (hot path) │
26//! │ └────┬────┘ │
27//! │ │ Err(Full/Unavailable) │
28//! │ ▼ │
29//! │ ┌─────────┐ │
30//! │ │ Spool │──► Disk (cold path) │
31//! │ └────┬────┘ │
32//! │ │ │
33//! │ Background drain task │
34//! │ (when primary recovers) │
35//! └─────────────────────────────────────┘
36//! ```
37//!
38//! ## Features
39//!
40//! - **Hot path first**: Always tries primary sink with timeout
41//! - **Automatic spillover**: Writes to disk only when primary fails
42//! - **Circuit breaker**: Avoids hammering a dead sink
43//! - **Background drain**: Recovers spooled messages when sink is healthy
44//! - **Configurable ordering**: Interleaved (default) or strict FIFO
45//! - **Multiple compression codecs**: LZ4 (default), Snappy, Zstd, None
46//!
47//! ## Example
48//!
49//! ```rust,ignore
50//! use hyperi_rustlib::tiered_sink::{TieredSink, TieredSinkConfig, Sink, SinkError};
51//!
52//! // Implement Sink for your backend
53//! struct MyKafkaSink { /* ... */ }
54//!
55//! #[async_trait::async_trait]
56//! impl Sink for MyKafkaSink {
57//! type Error = MyError;
58//!
59//! async fn try_send(&self, data: &[u8]) -> Result<(), SinkError<Self::Error>> {
60//! // Send to Kafka...
61//! Ok(())
62//! }
63//! }
64//!
65//! // Wrap with TieredSink
66//! let kafka = MyKafkaSink::new();
67//! let config = TieredSinkConfig::new("/var/spool/myapp.queue");
68//! let tiered = TieredSink::new(kafka, config).await?;
69//!
70//! // Use tiered - automatically spills to disk if Kafka is down
71//! tiered.send(b"my message").await?;
72//! ```
73
74mod circuit;
75mod codec;
76mod config;
77mod drainer;
78mod error;
79mod sink;
80mod tiered;
81
82pub use circuit::{CircuitBreaker, CircuitState};
83pub use codec::CompressionCodec;
84pub use config::{DiskAwareConfig, DrainStrategy, OrderingMode, TieredSinkConfig};
85pub use error::TieredSinkError;
86pub use sink::{Sink, SinkError};
87pub use tiered::TieredSink;
88
89/// Result type for tiered sink operations.
90pub type Result<T> = std::result::Result<T, TieredSinkError>;