Skip to main content

vortex_core/
traits.rs

1//! Trait definitions for the Vortex I/O boundary.
2//!
3//! These traits define the interface between your application and the outside world.
4//! In production, you implement them with real TCP, real disk, real clock.
5//! In simulation, Vortex swaps in deterministic implementations.
6
7use crate::NodeId;
8
9/// Error type for Vortex I/O operations.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum VortexError {
12    /// Network error (connection refused, timeout, etc.).
13    Network(String),
14    /// Storage error (disk full, corruption, I/O failure).
15    Storage(String),
16    /// Operation timed out.
17    Timeout,
18    /// Node is not available (crashed, partitioned).
19    Unavailable,
20    /// Custom application error.
21    Custom(String),
22}
23
24impl std::fmt::Display for VortexError {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        match self {
27            VortexError::Network(s) => write!(f, "network error: {s}"),
28            VortexError::Storage(s) => write!(f, "storage error: {s}"),
29            VortexError::Timeout => write!(f, "timeout"),
30            VortexError::Unavailable => write!(f, "unavailable"),
31            VortexError::Custom(s) => write!(f, "{s}"),
32        }
33    }
34}
35
36impl std::error::Error for VortexError {}
37
38pub type Result<T> = std::result::Result<T, VortexError>;
39
40/// Network I/O boundary trait.
41///
42/// In production: real TCP/UDP sockets.
43/// In simulation: `SimNetwork` with configurable latency, drops, partitions.
44pub trait VortexNetwork {
45    /// Send a message to a specific node.
46    fn send(&mut self, to: NodeId, payload: Vec<u8>) -> Result<()>;
47
48    /// Receive the next pending message, if any.
49    fn recv(&mut self) -> Option<(NodeId, Vec<u8>)>;
50
51    /// Broadcast a message to all known nodes.
52    fn broadcast(&mut self, nodes: &[NodeId], payload: Vec<u8>) -> Result<()> {
53        for &node in nodes {
54            self.send(node, payload.clone())?;
55        }
56        Ok(())
57    }
58}
59
60/// Persistent storage boundary trait.
61///
62/// In production: real filesystem, RocksDB, SQLite, etc.
63/// In simulation: `SimStorage` with crash/corruption fault injection.
64pub trait VortexStorage {
65    /// Get the value for a key.
66    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
67
68    /// Put a key-value pair.
69    fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
70
71    /// Delete a key.
72    fn delete(&mut self, key: &[u8]) -> Result<()>;
73
74    /// Scan a range of keys [start, end).
75    fn scan(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;
76
77    /// Apply a batch of operations atomically.
78    fn write_batch(&mut self, ops: Vec<StorageOp>) -> Result<()>;
79
80    /// Flush pending writes to durable storage.
81    fn flush(&mut self) -> Result<()>;
82
83    /// Create a point-in-time snapshot.
84    fn snapshot(&self) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;
85}
86
87/// A single storage operation (for batch writes).
88#[derive(Debug, Clone)]
89pub enum StorageOp {
90    Put { key: Vec<u8>, value: Vec<u8> },
91    Delete { key: Vec<u8> },
92}
93
94/// Clock boundary trait.
95///
96/// In production: `SystemTime::now()`.
97/// In simulation: `SimClock` with virtual time, skew, and drift injection.
98pub trait VortexClock {
99    /// Get the current time in microseconds.
100    fn now_us(&self) -> u64;
101
102    /// Sleep for the given duration (in microseconds).
103    /// In simulation, this schedules a timer event.
104    fn sleep_us(&self, duration_us: u64);
105}
106
107/// Task/event scheduling trait.
108///
109/// In production: tokio timers, OS timers, etc.
110/// In simulation: `SimScheduler` events.
111pub trait VortexScheduler {
112    /// Schedule a callback after `delay_ticks` ticks. Returns a handle.
113    fn schedule(&mut self, delay_ticks: u64, tag: String) -> u64;
114
115    /// Cancel a scheduled event by handle.
116    fn cancel(&mut self, handle: u64) -> bool;
117}