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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (c) 2025-2026 Adrian Robinson. Licensed under the AGPL-3.0.
// See LICENSE file in the project root for full license text.
//! # Sync Engine
//!
//! A high-performance, tiered storage engine for distributed data synchronization.
//!
//! ## Philosophy: Dumb Byte Router
//!
//! sync-engine stores `Vec<u8>` and routes to L1/L2/L3 based on caller options.
//! Compression, serialization, and data interpretation are the caller's responsibility.
//!
//! ## Architecture
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────┐
//! │ Ingest Layer │
//! │ • Accepts SyncItems via submit() / submit_with() │
//! │ • Backpressure control based on memory usage │
//! └─────────────────────────────────────────────────────────────┘
//! │
//! ▼
//! ┌─────────────────────────────────────────────────────────────┐
//! │ L1: In-Memory Cache │
//! │ • Moka cache for concurrent access │
//! │ • Tan-curve eviction under memory pressure │
//! └─────────────────────────────────────────────────────────────┘
//! │
//! (Batch flush via HybridBatcher)
//! ▼
//! ┌─────────────────────────────────────────────────────────────┐
//! │ L2: Redis Cache │
//! │ • Pipelined batch writes for throughput │
//! │ • Optional TTL per-item (via SubmitOptions) │
//! │ • EXISTS command for fast existence checks │
//! └─────────────────────────────────────────────────────────────┘
//! │
//! (Batch persist to ground truth)
//! ▼
//! ┌─────────────────────────────────────────────────────────────┐
//! │ L3: MySQL/SQLite Archive │
//! │ • Ground truth storage (BLOB column) │
//! │ • Cuckoo filter for fast existence checks │
//! │ • WAL fallback during outages │
//! └─────────────────────────────────────────────────────────────┘
//! ```
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use sync_engine::{SyncEngine, SyncEngineConfig, SyncItem};
//! use serde_json::json;
//! use tokio::sync::watch;
//!
//! #[tokio::main]
//! async fn main() {
//! let config = SyncEngineConfig {
//! redis_url: Some("redis://localhost:6379".into()),
//! sql_url: Some("mysql://user:pass@localhost/db".into()),
//! ..Default::default()
//! };
//!
//! let (_tx, rx) = watch::channel(config.clone());
//! let mut engine = SyncEngine::new(config, rx);
//!
//! // Start the engine (connects to backends)
//! engine.start().await.expect("Failed to start");
//!
//! // Submit items for sync
//! let item = SyncItem::from_json(
//! "uk.nhs.patient.record.12345".into(),
//! json!({"name": "John Doe", "nhs_number": "1234567890"})
//! );
//! engine.submit(item).await.expect("Failed to submit");
//!
//! // Retrieve items (L1 → L2 → L3 fallback)
//! if let Some(item) = engine.get("uk.nhs.patient.record.12345").await.unwrap() {
//! println!("Found: {:?}", item.content_as_json());
//! }
//!
//! engine.shutdown().await;
//! }
//! ```
//!
//! ## Features
//!
//! - **Tiered Caching**: L1 (memory) → L2 (Redis) → L3 (SQL) with automatic fallback
//! - **Binary Storage**: Store raw `Vec<u8>` - caller handles serialization/compression
//! - **Flexible Routing**: `SubmitOptions` controls which tiers receive data
//! - **TTL Support**: Per-item TTL for Redis cache entries
//! - **Batch Writes**: Configurable flush by count, size, or time
//! - **Cuckoo Filters**: Skip SQL queries when data definitely doesn't exist
//! - **WAL Durability**: Local SQLite WAL during MySQL outages
//! - **Backpressure**: Graceful degradation under memory pressure
//! - **Circuit Breakers**: Prevent cascade failures to backends
//! - **Retry Logic**: Configurable retry policies for transient failures
//!
//! ## Configuration
//!
//! See [`SyncEngineConfig`] for all configuration options.
//!
//! ## Modules
//!
//! - [`config`]: Engine configuration ([`SyncEngineConfig`])
//! - [`coordinator`]: The main [`SyncEngine`] orchestrating all components
//! - [`sync_item`]: Core data structure ([`SyncItem`], [`ContentType`])
//! - [`submit_options`]: Per-item routing options ([`SubmitOptions`], [`CacheTtl`])
//! - [`storage`]: Storage backends (Redis, SQL, Memory)
//! - [`batching`]: Hybrid batcher for efficient writes
//! - [`cuckoo`]: Probabilistic existence filters
//! - [`merkle`]: Merkle tree for sync verification
//! - [`resilience`]: Circuit breakers, retry logic, WAL
//! - [`eviction`]: Tan-curve eviction policy
//! - [`backpressure`]: Memory pressure handling
//! - [`search`]: RediSearch and SQL query translation
//! - [`cdc`]: Change Data Capture stream output
//! - [`metrics`]: OTEL-compatible metrics instrumentation
// Note: We don't expose a `tracing` module to avoid conflict with the tracing crate
pub use SyncEngineConfig;
pub use ;
pub use BackpressureLevel;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use RetryConfig;
pub use LatencyTimer;
pub use ;
pub use ;