Skip to main content

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:   FSL-1.1-ALv2
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>;