fix(914): thread-local ALL_OPS/VECTOR_CLOCK in cfg(test) so compaction tests don't race
Root cause was not the persist channel (the test-mode channel is unbounded and its receiver is leaked, so sends never fail). It was that `ALL_OPS` and `VECTOR_CLOCK` were process-wide `OnceLock` globals while `CRDT_STATE` was already thread-local — so one test thread's `apply_compaction` would prune another test thread's freshly-written ops out of the shared journal, and the subsequent `all_ops_json()` read in `compaction_reduces_ops` would return fewer than the 5 it had just written. Mirror the pattern already used for `CRDT_STATE` and `SnapshotState`: in `cfg(test)` use thread-local `OnceLock<Mutex<...>>`s for the op journal and vector clock, accessed via new `all_ops_lock()` / `vector_clock_lock()` helpers. Production code path is unchanged (still the global statics set during `init()`). Touches ops/read/snapshot call sites to go through the helpers. Note in passing that this overlaps backlog story 518; that story is about the production-side persist path, this is the cfg(test)-only journal-isolation slice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||
|
||||
use bft_json_crdt::json_crdt::*;
|
||||
|
||||
use super::state::{ALL_OPS, apply_and_persist, get_crdt, rebuild_index};
|
||||
use super::state::{all_ops_lock, apply_and_persist, get_crdt, rebuild_index};
|
||||
use super::types::{PipelineDoc, PipelineItemCrdt, PipelineItemView};
|
||||
use bft_json_crdt::op::ROOT_ID;
|
||||
|
||||
@@ -55,8 +55,7 @@ pub struct CrdtStateDump {
|
||||
pub fn dump_crdt_state(story_id_filter: Option<&str>) -> CrdtStateDump {
|
||||
let in_memory_state_loaded = get_crdt().is_some();
|
||||
|
||||
let persisted_ops_count = ALL_OPS
|
||||
.get()
|
||||
let persisted_ops_count = all_ops_lock()
|
||||
.and_then(|m| m.lock().ok().map(|v| v.len()))
|
||||
.unwrap_or(0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user