Files
huskies/server/src/crdt_state/state/apply.rs
T

51 lines
1.7 KiB
Rust
Raw Normal View History

2026-04-29 13:53:12 +00:00
//! Write path: create, sign, apply, persist, and broadcast a CRDT op.
//!
//! [`apply_and_persist`] is the single entry point for all CRDT mutations.
//! It invokes the caller's op-factory closure, signs the resulting op, applies
//! it to the live document, sends it to the persistence channel, and broadcasts
//! it to sync peers via [`super::SYNC_TX`].
use bft_json_crdt::json_crdt::JsonValue;
use bft_json_crdt::op::Op;
use super::super::types::CrdtEvent;
use super::{CrdtState, statics};
/// Create a CRDT op via `op_fn`, sign it, apply it, and send it to the
/// persistence channel. The closure receives `&mut CrdtState` so it can
/// mutably access the CRDT document, while `sign` only needs `&keypair`.
pub(in crate::crdt_state) fn apply_and_persist<F>(state: &mut CrdtState, op_fn: F)
where
F: FnOnce(&mut CrdtState) -> Op<JsonValue>,
{
let raw_op = op_fn(state);
let signed = raw_op.sign(&state.keypair);
state.crdt.apply(signed.clone());
if state.persist_tx.send(signed.clone()).is_err() {
let op_type = if signed.inner.is_deleted {
"Delete"
} else {
"Insert"
};
let seq = signed.inner.seq;
crate::slog_warn!(
"[crdt_persist] persist channel send failed: op_type={op_type} seq={seq}"
);
}
// Track in ALL_OPS + VECTOR_CLOCK, then broadcast to sync peers.
if let Ok(json) = serde_json::to_string(&signed) {
statics::track_op(&signed, json);
}
if let Some(tx) = statics::SYNC_TX.get() {
let _ = tx.send(signed);
}
}
/// Broadcast a CRDT event to all subscribers.
pub(in crate::crdt_state) fn emit_event(event: CrdtEvent) {
if let Some(tx) = statics::CRDT_EVENT_TX.get() {
let _ = tx.send(event);
}
}