mdcs-compaction
Compaction and stability subsystem for the MDCS (Merkle-Delta CRDT Store).
Overview
This crate implements Phase 5 of the MDCS architecture - the Compaction & Stability Subsystem. It provides mechanisms to bound metadata growth by:
- Tracking stability - determining which updates have been durably replicated
- Creating snapshots - capturing full CRDT state at stable frontiers
- Pruning history - safely removing DAG nodes older than the last snapshot
- Preventing resurrection - ensuring deleted items stay deleted after compaction
Architecture
The compaction subsystem is organized into five main components:
VersionVector
Compact representation of causal context using (replica_id, sequence_number) pairs:
use VersionVector;
let mut vv = new;
vv.increment;
vv.increment;
vv.set;
// Check dominance (causal ordering)
let vv2 = from_entries;
assert!;
Key features:
- Dominance checking (
dominates,strictly_dominates) - Concurrency detection (
is_concurrent_with) - Merging for LUB computation
- Diff computation for sync optimization
StabilityMonitor
Tracks the "known delivered frontier" across replicas to determine when updates are stable:
use ;
let mut monitor = new;
// Update local frontier after state changes
monitor.update_local_frontier;
// Process frontier updates from peers
monitor.update_peer_frontier;
// Check stability
if monitor.has_quorum
Configuration options:
min_peers_for_stability- minimum peers needed before stability checksrequire_all_peers- whether all known peers must acknowledgequorum_fraction- fraction of peers needed for quorumstale_peer_timeout- when to consider peers as stale
SnapshotManager
Manages periodic snapshots of CRDT state for efficient bootstrap and recovery:
use ;
use Hash;
let mut manager = new;
// Create a snapshot
let vv = from_entries;
let snapshot = new;
// Store and retrieve
let id = manager.store;
let latest = manager.latest;
Features:
- Automatic garbage collection of old snapshots
- Find snapshots that cover a given version vector
- Configurable snapshot frequency
Pruner
Identifies and removes DAG nodes that are safely purgeable:
use ;
// Configure pruning behavior
let policy = PruningPolicy ;
let pruner = with_policy;
// Identify prunable nodes (without modifying store)
let prunable = pruner.identify_prunable;
// Execute pruning on a PrunableStore
let result = pruner.execute_prune;
Safety guarantees:
- Never prunes nodes referenced by current heads
- Preserves configurable depth of history
- Optional genesis path preservation
- Verification utilities to prevent resurrection
Compactor
High-level orchestrator that coordinates all compaction components:
use ;
let mut compactor = new;
// Update local state
compactor.update_local_frontier;
// Process peer updates
compactor.process_peer_update;
// Create snapshots periodically
if compactor.should_snapshot
// Run automatic compaction
let result = compactor.compact?;
No-Resurrection Guarantee
A critical invariant of the compaction system is preventing "resurrection" of deleted items. This is achieved through:
-
Tombstone-free removal - The causal context tracks all created events, while the dot store only contains live data. An item is deleted when its dot is in the context but not the store.
-
Snapshot boundaries - Snapshots record which DAG roots they supersede. Nodes before the snapshot boundary can only be pruned if they're ancestors of those roots.
-
Verification - The
PruningVerifiercan check that pruning won't cause resurrection:
use PruningVerifier;
// Before pruning, verify safety
let result = verify_no_resurrection;
if result.is_ok
Integration with Merkle-Clock
The compaction subsystem integrates with mdcs-merkle to prune the Merkle-DAG while preserving causal integrity:
// The DAG stores the causal history
let = with_genesis;
// Snapshots reference DAG heads they supersede
let snapshot = new;
// Pruning removes ancestors of superseded roots
let prunable = pruner.identify_prunable;
Tests
The crate includes comprehensive tests:
- Unit tests - 33 tests covering all components
- Integration tests - 13 tests verifying:
- No resurrection after compaction
- Deterministic rebuild from snapshots
- Multi-replica stability tracking
- Quorum-based stability
- Pruning depth preservation
Run tests: