pub struct FsRelay { /* private fields */ }Expand description
The filesystem loopback relay: two (or more) DeviceLogs syncing
through a shared directory — the realistic single-user two-Mac case
(a shared volume, an external disk, a user-managed synced folder).
Layout under dir:
relay.lock— exclusive advisory lock held around every call (theOplogJournal/car-registryprotocol, but blocking: concurrent callers queue rather than fail);relay-state.json— roster + chains + latest-checkpoint pointer (temp + atomic rename per mutation);checkpoints/<checkpoint_hash>.checkpoint.json— content-addressed checkpoint files viaCheckpoint::save/load. Checkpoint files are immutable (the name IS the whole-record content address), so each isCheckpoint::load-verified once — on first sight by this handle — and then served from an in-memory cache; it is never re-hashed or re-fsync’d on subsequent (including read-only) calls. A tampering attacker in the shared folder is caught by the next process to open the relay (a fresh handle with a cold cache re-verifies), which is the actual two-Mac threat model; a handle never serves content it did not verify.
Semantics are identical to InMemoryRelay by construction — both
drive the same [RelayState] core; this type only adds durability and
cross-process mutual exclusion.
Implementations§
Trait Implementations§
Source§impl Relay for FsRelay
impl Relay for FsRelay
Source§fn register(&mut self, device_id: &str) -> Result<RosterEntry, RelayError>
fn register(&mut self, device_id: &str) -> Result<RosterEntry, RelayError>
Enroll (or touch) a device on the roster. Idempotent; push/pull/ack
auto-register on first contact.
Source§fn push(
&mut self,
device_id: &str,
ops: &[OpRecord],
) -> Result<PushOutcome, RelayError>
fn push( &mut self, device_id: &str, ops: &[OpRecord], ) -> Result<PushOutcome, RelayError>
Admit
device_id’s own journal-durable ops (in seq order) onto its
relay-held chain. Contract (B1, binding): the caller transmits only
ops that are already journal-durable on the device.Source§fn pull(
&mut self,
device_id: &str,
since: &Frontier,
) -> Result<PullResult, RelayError>
fn pull( &mut self, device_id: &str, since: &Frontier, ) -> Result<PullResult, RelayError>
Every retained op above
since (per-device seq cursor) + the latest
checkpoint pointer.Source§fn ack(
&mut self,
device_id: &str,
frontier: Hlc,
) -> Result<AckOutcome, RelayError>
fn ack( &mut self, device_id: &str, frontier: Hlc, ) -> Result<AckOutcome, RelayError>
Record a device’s fold frontier. Contract (B4, binding): the device
acks only what it has DURABLY folded (journaled), never merely
received.
Source§fn checkpoint_put(
&mut self,
device_id: &str,
checkpoint: &Checkpoint,
) -> Result<bool, RelayError>
fn checkpoint_put( &mut self, device_id: &str, checkpoint: &Checkpoint, ) -> Result<bool, RelayError>
Store a device-computed checkpoint. Verified, deduped on
checkpoint_hash (whole-record content address — contract from B4).
Returns false when the identical checkpoint was already stored.Source§fn checkpoint_get(&mut self) -> Result<Option<Checkpoint>, RelayError>
fn checkpoint_get(&mut self) -> Result<Option<Checkpoint>, RelayError>
The latest stored checkpoint (dominance-monotone pointer), if any.
Source§fn roster(&mut self) -> Result<Vec<RosterEntry>, RelayError>
fn roster(&mut self) -> Result<Vec<RosterEntry>, RelayError>
The device registry.
Source§fn stable_frontier(&mut self) -> Result<Option<Hlc>, RelayError>
fn stable_frontier(&mut self) -> Result<Option<Hlc>, RelayError>
min(acked) over active roster devices; None while any active
device has never acked (nothing is droppable then).Auto Trait Implementations§
impl !RefUnwindSafe for FsRelay
impl !UnwindSafe for FsRelay
impl Freeze for FsRelay
impl Send for FsRelay
impl Sync for FsRelay
impl Unpin for FsRelay
impl UnsafeUnpin for FsRelay
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more