51 lines
1.9 KiB
Rust
51 lines
1.9 KiB
Rust
|
|
//! Broadcast channels and op-tracking statics for the CRDT state layer.
|
||
|
|
//!
|
||
|
|
//! Provides the outbound sync channel ([`SYNC_TX`]), the event broadcast
|
||
|
|
//! channel ([`CRDT_EVENT_TX`]), and the in-memory op journal
|
||
|
|
//! ([`ALL_OPS`] / [`VECTOR_CLOCK`]) that tracks every applied op for
|
||
|
|
//! delta-sync.
|
||
|
|
|
||
|
|
use std::sync::{Mutex, OnceLock};
|
||
|
|
|
||
|
|
use bft_json_crdt::json_crdt::SignedOp;
|
||
|
|
use tokio::sync::broadcast;
|
||
|
|
|
||
|
|
use super::super::VectorClock;
|
||
|
|
use super::super::hex;
|
||
|
|
use super::super::types::CrdtEvent;
|
||
|
|
|
||
|
|
/// Broadcast channel for CRDT events (stage transitions, etc.).
|
||
|
|
pub(super) static CRDT_EVENT_TX: OnceLock<broadcast::Sender<CrdtEvent>> = OnceLock::new();
|
||
|
|
|
||
|
|
/// Broadcast channel for outbound ops to sync peers.
|
||
|
|
pub(in crate::crdt_state) static SYNC_TX: OnceLock<broadcast::Sender<SignedOp>> = OnceLock::new();
|
||
|
|
|
||
|
|
/// All persisted ops as JSON strings, in causal (insertion) order.
|
||
|
|
///
|
||
|
|
/// Pub(crate) so that `crdt_snapshot` can access it for compaction.
|
||
|
|
pub(crate) static ALL_OPS: OnceLock<Mutex<Vec<String>>> = OnceLock::new();
|
||
|
|
|
||
|
|
/// Live vector clock tracking op counts per author.
|
||
|
|
///
|
||
|
|
/// Updated in lockstep with `ALL_OPS` — every time an op is appended to the
|
||
|
|
/// journal, the corresponding author's count is incremented here. This avoids
|
||
|
|
/// re-parsing all ops when a peer requests `our_vector_clock()`.
|
||
|
|
pub(crate) static VECTOR_CLOCK: OnceLock<Mutex<VectorClock>> = OnceLock::new();
|
||
|
|
|
||
|
|
/// Append an op's JSON to `ALL_OPS` and bump the author's count in `VECTOR_CLOCK`.
|
||
|
|
///
|
||
|
|
/// Centralises the bookkeeping that must stay in sync between the two statics.
|
||
|
|
pub(in crate::crdt_state) fn track_op(signed: &SignedOp, json: String) {
|
||
|
|
if let Some(all) = ALL_OPS.get()
|
||
|
|
&& let Ok(mut v) = all.lock()
|
||
|
|
{
|
||
|
|
v.push(json);
|
||
|
|
}
|
||
|
|
if let Some(vc) = VECTOR_CLOCK.get()
|
||
|
|
&& let Ok(mut clock) = vc.lock()
|
||
|
|
{
|
||
|
|
let author_hex = hex::encode(&signed.author());
|
||
|
|
*clock.entry(author_hex).or_insert(0) += 1;
|
||
|
|
}
|
||
|
|
}
|