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
// Project: hyperi-rustlib
// File: src/tiered_sink/mod.rs
// Purpose: Tiered sink with disk spillover for resilient message delivery
// Language: Rust
//
// License: FSL-1.1-ALv2
// Copyright: (c) 2026 HYPERI PTY LIMITED
//! Tiered sink with automatic disk spillover for resilient message delivery.
//!
//! This module provides a wrapper around any async sink (Kafka, S3, HTTP, etc.)
//! that automatically spills messages to disk when the primary sink is unavailable
//! or backpressuring, then drains them back when the sink recovers.
//!
//! ## Design
//!
//! ```text
//! ┌─────────────────────────────────────┐
//! │ TieredSink │
//! │ │
//! Message ────────►│ try_send() to primary sink │
//! │ │ │
//! │ ▼ │
//! │ ┌─────────┐ │
//! │ │ Success │──► Done (hot path) │
//! │ └────┬────┘ │
//! │ │ Err(Full/Unavailable) │
//! │ ▼ │
//! │ ┌─────────┐ │
//! │ │ Spool │──► Disk (cold path) │
//! │ └────┬────┘ │
//! │ │ │
//! │ Background drain task │
//! │ (when primary recovers) │
//! └─────────────────────────────────────┘
//! ```
//!
//! ## Features
//!
//! - **Hot path first**: Always tries primary sink with timeout
//! - **Automatic spillover**: Writes to disk only when primary fails
//! - **Circuit breaker**: Avoids hammering a dead sink
//! - **Background drain**: Recovers spooled messages when sink is healthy
//! - **Configurable ordering**: Interleaved (default) or strict FIFO
//! - **Multiple compression codecs**: LZ4 (default), Snappy, Zstd, None
//!
//! ## Example
//!
//! ```rust,ignore
//! use hyperi_rustlib::tiered_sink::{TieredSink, TieredSinkConfig, Sink, SinkError};
//!
//! // Implement Sink for your backend
//! struct MyKafkaSink { /* ... */ }
//!
//! #[async_trait::async_trait]
//! impl Sink for MyKafkaSink {
//! type Error = MyError;
//!
//! async fn try_send(&self, data: &[u8]) -> Result<(), SinkError<Self::Error>> {
//! // Send to Kafka...
//! Ok(())
//! }
//! }
//!
//! // Wrap with TieredSink
//! let kafka = MyKafkaSink::new();
//! let config = TieredSinkConfig::new("/var/spool/myapp.queue");
//! let tiered = TieredSink::new(kafka, config).await?;
//!
//! // Use tiered - automatically spills to disk if Kafka is down
//! tiered.send(b"my message").await?;
//! ```
pub use ;
pub use CompressionCodec;
pub use ;
pub use TieredSinkError;
pub use ;
pub use TieredSink;
/// Result type for tiered sink operations.
pub type Result<T> = Result;