@feltdb/core 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/create/package-versions.js +1 -1
  2. package/dist/create/server-source/Cargo.lock +165 -0
  3. package/dist/create/server-source/Cargo.toml +9 -0
  4. package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
  5. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
  6. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
  7. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
  8. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
  9. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
  10. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
  11. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
  12. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
  13. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
  14. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
  15. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
  19. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
  20. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
  21. package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
  22. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
  23. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
  24. package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
  25. package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
  26. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
  27. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
  28. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
  29. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
  30. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
  31. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
  32. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
  33. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
  34. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
  35. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
  36. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
  37. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
  38. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
  39. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
  40. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
  41. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
  42. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
  43. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
  44. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
  45. package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
  46. package/dist/create/server-source/crates/feltdb/src/lib.rs +507 -6
  47. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
  48. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
  49. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
  50. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
  51. package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
  52. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
  53. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
  54. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
  55. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
  56. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
  57. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
  58. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
  59. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
  60. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
  61. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
  62. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +79 -70
  63. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
  64. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
  65. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
  66. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
  67. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
  68. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
  69. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
  70. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
  71. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
  72. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
  73. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
  74. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
  75. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
  76. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
  77. package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
  78. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
  79. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
  80. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
  81. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
  82. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
  83. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
  84. package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
  85. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
  86. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +13 -4
  87. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
  88. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
  89. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
  90. package/dist/create/server-source/crates/feltdb/src/state_model.rs +1514 -537
  91. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
  92. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
  93. package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
  94. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
  95. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
  96. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
  97. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
  98. package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
  99. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
  100. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
  101. package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
  102. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +3 -4
  103. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
  104. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +288 -0
  105. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
  106. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
  107. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
  108. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
  109. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
  110. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +2 -1
  111. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +80 -25
  112. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
  113. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
  114. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
  115. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
  116. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
  117. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
  118. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
  119. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
  120. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
  121. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1032 -0
  122. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
  123. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
  124. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
  125. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
  126. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
  127. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
  128. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
  129. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
  130. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
  131. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
  132. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
  133. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
  134. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
  135. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
  136. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
  137. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
  138. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +2 -1
  139. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
  140. package/dist/create/server-source/crates/feltdb-server/src/main.rs +326 -6
  141. package/dist/studio-app/assets/{feltdb_wasm-CVQWgXO-.js → feltdb_wasm-DaNwCLRX.js} +1 -1
  142. package/dist/studio-app/assets/feltdb_wasm_bg-DnsHNv6g.wasm +0 -0
  143. package/dist/studio-app/assets/{index-DwgNAIIX.js → index-j8IlhNqJ.js} +1 -1
  144. package/dist/studio-app/index.html +1 -1
  145. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  146. package/dist/workload.d.ts +2 -1
  147. package/dist/workload.d.ts.map +1 -1
  148. package/package.json +1 -1
  149. package/dist/studio-app/assets/feltdb_wasm_bg-CNVpvaZV.wasm +0 -0
@@ -7,7 +7,6 @@
7
7
  /// - Relationship access patterns
8
8
  /// - Materialized views and projections
9
9
  /// - Multi-key operations
10
-
11
10
  use serde::{Deserialize, Serialize};
12
11
  use std::collections::HashMap;
13
12
 
@@ -142,7 +141,11 @@ impl ProductionAPI {
142
141
  .ok_or_else(|| format!("Resource not found: {}", id))
143
142
  }
144
143
 
145
- pub fn read_many(&self, ids: &[&str], _options: ReadOptions) -> Result<Vec<StateValue>, String> {
144
+ pub fn read_many(
145
+ &self,
146
+ ids: &[&str],
147
+ _options: ReadOptions,
148
+ ) -> Result<Vec<StateValue>, String> {
146
149
  let mut results = Vec::new();
147
150
  for id in ids {
148
151
  if let Some(value) = self.state_store.get(*id) {
@@ -152,7 +155,11 @@ impl ProductionAPI {
152
155
  Ok(results)
153
156
  }
154
157
 
155
- pub fn write(&mut self, mutation: Mutation, options: WriteOptions) -> Result<MutationResult, String> {
158
+ pub fn write(
159
+ &mut self,
160
+ mutation: Mutation,
161
+ options: WriteOptions,
162
+ ) -> Result<MutationResult, String> {
156
163
  if let Some(ref key) = options.idempotency_key {
157
164
  if let Some(existing) = self.state_store.get(&mutation.resource_id) {
158
165
  return Ok(MutationResult {
@@ -177,7 +184,8 @@ impl ProductionAPI {
177
184
  updated_at: now,
178
185
  };
179
186
 
180
- self.state_store.insert(mutation.resource_id.clone(), value.clone());
187
+ self.state_store
188
+ .insert(mutation.resource_id.clone(), value.clone());
181
189
 
182
190
  Ok(MutationResult {
183
191
  success: true,
@@ -209,7 +217,10 @@ impl ProductionAPI {
209
217
  Ok(results)
210
218
  }
211
219
 
212
- pub fn transaction(&mut self, request: TransactionRequest) -> Result<TransactionResult, String> {
220
+ pub fn transaction(
221
+ &mut self,
222
+ request: TransactionRequest,
223
+ ) -> Result<TransactionResult, String> {
213
224
  self.transaction_id_counter += 1;
214
225
  let transaction_id = format!("tx-{}", self.transaction_id_counter);
215
226
 
@@ -246,13 +257,12 @@ impl ProductionAPI {
246
257
  .push(target);
247
258
  }
248
259
 
249
- pub fn get_relationships(&self, query: RelationshipQuery) -> Result<RelationshipResult, String> {
260
+ pub fn get_relationships(
261
+ &self,
262
+ query: RelationshipQuery,
263
+ ) -> Result<RelationshipResult, String> {
250
264
  let key = format!("{}:{}", query.source_id, query.relationship);
251
- let targets = self
252
- .relationships
253
- .get(&key)
254
- .cloned()
255
- .unwrap_or_default();
265
+ let targets = self.relationships.get(&key).cloned().unwrap_or_default();
256
266
 
257
267
  Ok(RelationshipResult {
258
268
  source_id: query.source_id,
@@ -359,8 +369,16 @@ mod tests {
359
369
  #[test]
360
370
  fn test_relationships() {
361
371
  let mut api = ProductionAPI::new();
362
- api.add_relationship("user-1".to_string(), "follows".to_string(), "user-2".to_string());
363
- api.add_relationship("user-1".to_string(), "follows".to_string(), "user-3".to_string());
372
+ api.add_relationship(
373
+ "user-1".to_string(),
374
+ "follows".to_string(),
375
+ "user-2".to_string(),
376
+ );
377
+ api.add_relationship(
378
+ "user-1".to_string(),
379
+ "follows".to_string(),
380
+ "user-3".to_string(),
381
+ );
364
382
 
365
383
  let result = api
366
384
  .get_relationships(RelationshipQuery {
@@ -5,7 +5,6 @@
5
5
  /// - Latency contract enforcement
6
6
  /// - Performance degradation detection
7
7
  /// - Query optimization recommendations
8
-
9
8
  use serde::{Deserialize, Serialize};
10
9
  use std::collections::HashMap;
11
10
  use std::time::{Duration, Instant};
@@ -156,7 +155,11 @@ impl QueryPerformanceTracker {
156
155
  for metric in &self.metrics {
157
156
  csv.push_str(&format!(
158
157
  "{},{},{},{},{}\n",
159
- metric.timestamp, metric.query_type, metric.duration_us, metric.index_name, metric.result_count
158
+ metric.timestamp,
159
+ metric.query_type,
160
+ metric.duration_us,
161
+ metric.index_name,
162
+ metric.result_count
160
163
  ));
161
164
  }
162
165
  csv
@@ -187,12 +190,7 @@ mod tests {
187
190
  std::thread::sleep(Duration::from_micros(50));
188
191
  let elapsed = timer.elapsed_us();
189
192
 
190
- tracker.record_query(
191
- "index_lookup".to_string(),
192
- "idx_1".to_string(),
193
- 10,
194
- elapsed,
195
- );
193
+ tracker.record_query("index_lookup".to_string(), "idx_1".to_string(), 10, elapsed);
196
194
 
197
195
  let stats = tracker.get_stats("index_lookup").unwrap();
198
196
  assert_eq!(stats.count, 1);
@@ -8,7 +8,6 @@
8
8
  /// - After index deletion (rebuild index from scratch)
9
9
  ///
10
10
  /// All paths must converge to identical state_hash.
11
-
12
11
  use crate::operation_log::{MemoryOperationLog, OperationLogEntry};
13
12
  use crate::state_hash::{CanonicalState, StateHash};
14
13
  use crate::state_transition_store::MemoryStateTransitionStore;
@@ -46,7 +45,10 @@ pub struct ReplayFuzzer {
46
45
  }
47
46
 
48
47
  impl ReplayFuzzer {
49
- pub fn new(operation_log: MemoryOperationLog, transition_store: MemoryStateTransitionStore) -> Self {
48
+ pub fn new(
49
+ operation_log: MemoryOperationLog,
50
+ transition_store: MemoryStateTransitionStore,
51
+ ) -> Self {
50
52
  Self {
51
53
  operation_log,
52
54
  transition_store,
@@ -99,9 +101,7 @@ impl ReplayFuzzer {
99
101
  let log_size = self.operation_log.size();
100
102
  if snapshot_at >= log_size {
101
103
  return ReplayPath {
102
- scenario: ReplayScenario::AfterSnapshot {
103
- snapshot_at,
104
- },
104
+ scenario: ReplayScenario::AfterSnapshot { snapshot_at },
105
105
  final_state_hash: StateHash::from_hex("snapshot_beyond_log".to_string()),
106
106
  operations_replayed: 0,
107
107
  transitions_created: 0,
@@ -137,12 +137,16 @@ impl AcknowledgementStore {
137
137
  pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, AcknowledgementError> {
138
138
  let path = path.as_ref().to_path_buf();
139
139
  let acknowledgements = if path.exists() {
140
- let bytes = std::fs::read(&path).map_err(|e| AcknowledgementError::Io(e.to_string()))?;
140
+ let bytes =
141
+ std::fs::read(&path).map_err(|e| AcknowledgementError::Io(e.to_string()))?;
141
142
  serde_json::from_slice(&bytes).map_err(|e| AcknowledgementError::Io(e.to_string()))?
142
143
  } else {
143
144
  BTreeMap::new()
144
145
  };
145
- Ok(Self { path, acknowledgements })
146
+ Ok(Self {
147
+ path,
148
+ acknowledgements,
149
+ })
146
150
  }
147
151
 
148
152
  fn persist(&self) -> Result<(), AcknowledgementError> {
@@ -154,10 +158,12 @@ impl AcknowledgementStore {
154
158
  .map_err(|e| AcknowledgementError::Io(e.to_string()))?;
155
159
  {
156
160
  use std::io::Write;
157
- let mut file =
158
- std::fs::File::create(&temp).map_err(|e| AcknowledgementError::Io(e.to_string()))?;
159
- file.write_all(&bytes).map_err(|e| AcknowledgementError::Io(e.to_string()))?;
160
- file.sync_all().map_err(|e| AcknowledgementError::Io(e.to_string()))?;
161
+ let mut file = std::fs::File::create(&temp)
162
+ .map_err(|e| AcknowledgementError::Io(e.to_string()))?;
163
+ file.write_all(&bytes)
164
+ .map_err(|e| AcknowledgementError::Io(e.to_string()))?;
165
+ file.sync_all()
166
+ .map_err(|e| AcknowledgementError::Io(e.to_string()))?;
161
167
  }
162
168
  std::fs::rename(&temp, &self.path).map_err(|e| AcknowledgementError::Io(e.to_string()))?;
163
169
  if let Some(parent) = self.path.parent() {
@@ -227,7 +233,9 @@ impl AcknowledgementStore {
227
233
  // No required replicas at all. Still not a licence: a node with no
228
234
  // membership has not established that it is alone, it has
229
235
  // established nothing.
230
- return ReclamationEvidence::Blocked { waiting_on: Vec::new() };
236
+ return ReclamationEvidence::Blocked {
237
+ waiting_on: Vec::new(),
238
+ };
231
239
  }
232
240
 
233
241
  let missing: Vec<String> = required
@@ -236,7 +244,9 @@ impl AcknowledgementStore {
236
244
  .cloned()
237
245
  .collect();
238
246
  if !missing.is_empty() {
239
- return ReclamationEvidence::Blocked { waiting_on: missing };
247
+ return ReclamationEvidence::Blocked {
248
+ waiting_on: missing,
249
+ };
240
250
  }
241
251
 
242
252
  // The minimum over every required replica, component-wise. A frontier
@@ -259,7 +269,10 @@ impl AcknowledgementStore {
259
269
  frontier.clocks.insert(origin, lowest);
260
270
  }
261
271
  }
262
- ReclamationEvidence::SafeThrough { frontier, covered: required }
272
+ ReclamationEvidence::SafeThrough {
273
+ frontier,
274
+ covered: required,
275
+ }
263
276
  }
264
277
  }
265
278
 
@@ -328,12 +341,17 @@ mod tests {
328
341
  fn a_required_replica_with_no_acknowledgement_blocks() {
329
342
  let dir = tempfile::tempdir().unwrap();
330
343
  let mut acks = store(&dir);
331
- acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"])).unwrap();
344
+ acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"]))
345
+ .unwrap();
332
346
 
333
347
  let evidence = acks.evidence(&["ra".into(), "rb".into(), "rc".into()]);
334
348
  match evidence {
335
349
  ReclamationEvidence::Blocked { waiting_on } => {
336
- assert_eq!(waiting_on, vec!["ra", "rc"], "and it names who it waits for");
350
+ assert_eq!(
351
+ waiting_on,
352
+ vec!["ra", "rc"],
353
+ "and it names who it waits for"
354
+ );
337
355
  }
338
356
  other => panic!("missing acknowledgement must block, got {other:?}"),
339
357
  }
@@ -347,7 +365,8 @@ mod tests {
347
365
  let dir = tempfile::tempdir().unwrap();
348
366
  let mut acks = store(&dir);
349
367
  acks.record(ack("ra", &[("A", 3)], &["ra", "rb"])).unwrap();
350
- acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"])).unwrap();
368
+ acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"]))
369
+ .unwrap();
351
370
 
352
371
  let local = vec!["ra".to_string(), "rb".to_string()];
353
372
  assert_eq!(acks.required_union(&local), vec!["ra", "rb", "rc"]);
@@ -363,7 +382,10 @@ mod tests {
363
382
  // alone. It has established nothing, and nothing is what it may act on.
364
383
  let dir = tempfile::tempdir().unwrap();
365
384
  let acks = store(&dir);
366
- assert!(matches!(acks.evidence(&[]), ReclamationEvidence::Blocked { .. }));
385
+ assert!(matches!(
386
+ acks.evidence(&[]),
387
+ ReclamationEvidence::Blocked { .. }
388
+ ));
367
389
  }
368
390
 
369
391
  #[test]
@@ -395,8 +417,10 @@ mod tests {
395
417
  fn the_safe_frontier_is_the_minimum_over_every_required_replica() {
396
418
  let dir = tempfile::tempdir().unwrap();
397
419
  let mut acks = store(&dir);
398
- acks.record(ack("ra", &[("A", 9), ("B", 4)], &["ra", "rb"])).unwrap();
399
- acks.record(ack("rb", &[("A", 5), ("B", 6)], &["ra", "rb"])).unwrap();
420
+ acks.record(ack("ra", &[("A", 9), ("B", 4)], &["ra", "rb"]))
421
+ .unwrap();
422
+ acks.record(ack("rb", &[("A", 5), ("B", 6)], &["ra", "rb"]))
423
+ .unwrap();
400
424
 
401
425
  match acks.evidence(&["ra".into(), "rb".into()]) {
402
426
  ReclamationEvidence::SafeThrough { frontier, covered } => {
@@ -415,7 +439,8 @@ mod tests {
415
439
  // anything is safe through.
416
440
  let dir = tempfile::tempdir().unwrap();
417
441
  let mut acks = store(&dir);
418
- acks.record(ack("ra", &[("A", 4), ("C", 9)], &["ra", "rb"])).unwrap();
442
+ acks.record(ack("ra", &[("A", 4), ("C", 9)], &["ra", "rb"]))
443
+ .unwrap();
419
444
  acks.record(ack("rb", &[("A", 4)], &["ra", "rb"])).unwrap();
420
445
 
421
446
  match acks.evidence(&["ra".into(), "rb".into()]) {
@@ -437,7 +462,8 @@ mod tests {
437
462
  let dir = tempfile::tempdir().unwrap();
438
463
  {
439
464
  let mut acks = store(&dir);
440
- acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"])).unwrap();
465
+ acks.record(ack("rb", &[("A", 3)], &["ra", "rb", "rc"]))
466
+ .unwrap();
441
467
  }
442
468
  let recovered = store(&dir);
443
469
  match recovered.evidence(&["ra".into(), "rb".into()]) {
@@ -464,7 +490,11 @@ mod tests {
464
490
 
465
491
  let recovered = store(&dir);
466
492
  assert_eq!(
467
- recovered.get("rb").unwrap().origin_sequence_high_water.get("A"),
493
+ recovered
494
+ .get("rb")
495
+ .unwrap()
496
+ .origin_sequence_high_water
497
+ .get("A"),
468
498
  Some(&7),
469
499
  );
470
500
  }
@@ -146,19 +146,23 @@ impl MembershipStore {
146
146
  /// directory. Membership is what will later authorise deleting history, so
147
147
  /// it is written with the same care as the log it will authorise deleting.
148
148
  fn persist(&self) -> Result<(), MembershipError> {
149
- let Some(cluster) = &self.cluster else { return Ok(()) };
149
+ let Some(cluster) = &self.cluster else {
150
+ return Ok(());
151
+ };
150
152
  if let Some(parent) = self.path.parent() {
151
153
  std::fs::create_dir_all(parent).map_err(|e| MembershipError::Io(e.to_string()))?;
152
154
  }
153
155
  let temp = self.path.with_extension("tmp");
154
- let bytes = serde_json::to_vec_pretty(cluster)
155
- .map_err(|e| MembershipError::Io(e.to_string()))?;
156
+ let bytes =
157
+ serde_json::to_vec_pretty(cluster).map_err(|e| MembershipError::Io(e.to_string()))?;
156
158
  {
157
159
  use std::io::Write;
158
- let mut file = std::fs::File::create(&temp)
160
+ let mut file =
161
+ std::fs::File::create(&temp).map_err(|e| MembershipError::Io(e.to_string()))?;
162
+ file.write_all(&bytes)
163
+ .map_err(|e| MembershipError::Io(e.to_string()))?;
164
+ file.sync_all()
159
165
  .map_err(|e| MembershipError::Io(e.to_string()))?;
160
- file.write_all(&bytes).map_err(|e| MembershipError::Io(e.to_string()))?;
161
- file.sync_all().map_err(|e| MembershipError::Io(e.to_string()))?;
162
166
  }
163
167
  std::fs::rename(&temp, &self.path).map_err(|e| MembershipError::Io(e.to_string()))?;
164
168
  if let Some(parent) = self.path.parent() {
@@ -435,7 +439,11 @@ mod tests {
435
439
  cluster.suspect_replica("rc").unwrap();
436
440
  cluster.mark_seen("rc").unwrap();
437
441
  let seen = cluster.get_members().into_iter().next().unwrap();
438
- assert_eq!(seen.status, ReplicaStatus::Active, "contact reinstates a suspected replica");
442
+ assert_eq!(
443
+ seen.status,
444
+ ReplicaStatus::Active,
445
+ "contact reinstates a suspected replica"
446
+ );
439
447
  assert!(seen.last_seen_at_ms.is_some());
440
448
 
441
449
  cluster.remove_replica("rc").unwrap();
@@ -503,7 +511,10 @@ mod tests {
503
511
  fn membership_operations_need_a_cluster() {
504
512
  let dir = tempfile::tempdir().unwrap();
505
513
  let mut cluster = store(&dir);
506
- assert!(matches!(cluster.join_replica("ra", "A"), Err(MembershipError::NoCluster)));
514
+ assert!(matches!(
515
+ cluster.join_replica("ra", "A"),
516
+ Err(MembershipError::NoCluster)
517
+ ));
507
518
  cluster.create_cluster("c1").unwrap();
508
519
  assert!(matches!(
509
520
  cluster.create_cluster("c2"),
@@ -523,7 +534,10 @@ mod tests {
523
534
  cluster.join_replica("ra", "A").unwrap();
524
535
  cluster.approve_replica("ra").unwrap();
525
536
  assert!(
526
- matches!(cluster.approve_replica("ra"), Err(MembershipError::NotJoining(_))),
537
+ matches!(
538
+ cluster.approve_replica("ra"),
539
+ Err(MembershipError::NotJoining(_))
540
+ ),
527
541
  "approving twice is not a silent no-op"
528
542
  );
529
543
  }
@@ -648,7 +662,9 @@ mod tests {
648
662
  let mut cluster = MembershipStore::open(&path).unwrap();
649
663
  cluster.create_cluster("c1").unwrap();
650
664
  for index in 0..20 {
651
- cluster.join_replica(&format!("r{index}"), &format!("N{index}")).unwrap();
665
+ cluster
666
+ .join_replica(&format!("r{index}"), &format!("N{index}"))
667
+ .unwrap();
652
668
  let observed = MembershipStore::open(&path).unwrap();
653
669
  assert_eq!(
654
670
  observed.get_members().len(),
@@ -656,6 +672,9 @@ mod tests {
656
672
  "every observation is of a complete cluster"
657
673
  );
658
674
  }
659
- assert!(!path.with_extension("tmp").exists(), "no temp file is left at rest");
675
+ assert!(
676
+ !path.with_extension("tmp").exists(),
677
+ "no temp file is left at rest"
678
+ );
660
679
  }
661
680
  }
@@ -6,7 +6,6 @@
6
6
  /// - Routing messages from leader to followers
7
7
  /// - Acknowledgment tracking
8
8
  /// - Retry logic for lost messages
9
-
10
9
  use crate::distributed_transactions::ReplicationMessage;
11
10
  use std::collections::{HashMap, VecDeque};
12
11
  use std::sync::atomic::{AtomicU64, Ordering};
@@ -67,7 +66,10 @@ impl PeerReplicationQueue {
67
66
  }
68
67
 
69
68
  pub fn pending_count(&self) -> usize {
70
- self.messages.iter().filter(|m| m.status == DeliveryStatus::Pending).count()
69
+ self.messages
70
+ .iter()
71
+ .filter(|m| m.status == DeliveryStatus::Pending)
72
+ .count()
71
73
  }
72
74
 
73
75
  pub fn next_pending(&mut self) -> Option<TrackedMessage> {
@@ -103,7 +105,8 @@ impl ReplicationManager {
103
105
 
104
106
  /// Register a peer to receive replication messages
105
107
  pub fn register_peer(&mut self, peer_id: String) {
106
- self.peer_queues.insert(peer_id.clone(), PeerReplicationQueue::new(peer_id));
108
+ self.peer_queues
109
+ .insert(peer_id.clone(), PeerReplicationQueue::new(peer_id));
107
110
  }
108
111
 
109
112
  /// Enqueue a message for replication to all peers
@@ -2,7 +2,6 @@
2
2
  ///
3
3
  /// Decouples ReplicationMessage handling from transport details.
4
4
  /// Works with typed messages (ReplicationMessage) rather than raw bytes.
5
-
6
5
  use crate::distributed_transactions::ReplicationMessage;
7
6
  use std::sync::atomic::{AtomicU64, Ordering};
8
7
  use std::sync::Arc;
@@ -71,7 +70,8 @@ impl ProtocolMetrics {
71
70
 
72
71
  pub fn record_receive(&self, bytes: usize) {
73
72
  self.messages_received.fetch_add(1, Ordering::Relaxed);
74
- self.bytes_received.fetch_add(bytes as u64, Ordering::Relaxed);
73
+ self.bytes_received
74
+ .fetch_add(bytes as u64, Ordering::Relaxed);
75
75
  }
76
76
 
77
77
  pub fn record_error(&self) {
@@ -79,7 +79,8 @@ impl ProtocolMetrics {
79
79
  }
80
80
 
81
81
  pub fn record_connection_state_change(&self) {
82
- self.connection_state_changes.fetch_add(1, Ordering::Relaxed);
82
+ self.connection_state_changes
83
+ .fetch_add(1, Ordering::Relaxed);
83
84
  }
84
85
 
85
86
  pub fn get_messages_sent(&self) -> u64 {
@@ -8,7 +8,6 @@
8
8
  * - Query routing to appropriate shards
9
9
  * - Data migration between shards
10
10
  */
11
-
12
11
  use serde::{Deserialize, Serialize};
13
12
  use std::collections::{BTreeMap, HashMap, HashSet};
14
13
 
@@ -189,7 +188,9 @@ impl ShardManager {
189
188
  }
190
189
  "delete" => {
191
190
  metrics.entry_count = metrics.entry_count.saturating_sub(records_affected);
192
- metrics.size_bytes = metrics.size_bytes.saturating_sub(size_bytes.min(metrics.size_bytes));
191
+ metrics.size_bytes = metrics
192
+ .size_bytes
193
+ .saturating_sub(size_bytes.min(metrics.size_bytes));
193
194
  }
194
195
  _ => {}
195
196
  }
@@ -253,7 +254,9 @@ impl ShardManager {
253
254
  }
254
255
 
255
256
  // High write load
256
- if write_std_dev > 0.0 && (metrics.writes as f64 - avg_writes).abs() > write_std_dev * 2.0 {
257
+ if write_std_dev > 0.0
258
+ && (metrics.writes as f64 - avg_writes).abs() > write_std_dev * 2.0
259
+ {
257
260
  alerts.push(HotspotAlert {
258
261
  shard_id: metrics.shard_id.clone(),
259
262
  reason: "High write load".to_string(),
@@ -269,7 +272,9 @@ impl ShardManager {
269
272
  }
270
273
 
271
274
  // Data imbalance
272
- if entry_std_dev > 0.0 && (metrics.entry_count as f64 - avg_entries).abs() > entry_std_dev * 3.0 {
275
+ if entry_std_dev > 0.0
276
+ && (metrics.entry_count as f64 - avg_entries).abs() > entry_std_dev * 3.0
277
+ {
273
278
  alerts.push(HotspotAlert {
274
279
  shard_id: metrics.shard_id.clone(),
275
280
  reason: "Data imbalance".to_string(),
@@ -297,13 +302,22 @@ impl ShardManager {
297
302
  for hotspot in hotspots {
298
303
  if hotspot.severity == "high" {
299
304
  // Find the overloaded shard
300
- if let Some(shard_range) = self.shard_ranges.iter().find(|r| r.shard_id == hotspot.shard_id) {
305
+ if let Some(shard_range) = self
306
+ .shard_ranges
307
+ .iter()
308
+ .find(|r| r.shard_id == hotspot.shard_id)
309
+ {
301
310
  // Split the hash range in half
302
- let mid_hash = (shard_range.start_hash as u128 + shard_range.end_hash as u128) / 2;
311
+ let mid_hash =
312
+ (shard_range.start_hash as u128 + shard_range.end_hash as u128) / 2;
303
313
  let mid_hash = mid_hash as u64;
304
314
 
305
315
  // Create a new shard ID for the split
306
- let new_shard_id = ShardId(format!("{}-split-{}", hotspot.shard_id.0, current_time_ms()));
316
+ let new_shard_id = ShardId(format!(
317
+ "{}-split-{}",
318
+ hotspot.shard_id.0,
319
+ current_time_ms()
320
+ ));
307
321
 
308
322
  operations.push(RebalanceOperation {
309
323
  source_shard: hotspot.shard_id.clone(),
@@ -415,7 +429,10 @@ mod tests {
415
429
  ShardingStrategy::ConsistentHash,
416
430
  );
417
431
 
418
- let shards = vec![ShardId("shard-0".to_string()), ShardId("shard-1".to_string())];
432
+ let shards = vec![
433
+ ShardId("shard-0".to_string()),
434
+ ShardId("shard-1".to_string()),
435
+ ];
419
436
  let mut replicas = HashMap::new();
420
437
  replicas.insert("shard-0".to_string(), vec!["node-1".to_string()]);
421
438
  replicas.insert("shard-1".to_string(), vec!["node-2".to_string()]);
@@ -435,7 +452,10 @@ mod tests {
435
452
  ShardingStrategy::ConsistentHash,
436
453
  );
437
454
 
438
- let shards = vec![ShardId("shard-0".to_string()), ShardId("shard-1".to_string())];
455
+ let shards = vec![
456
+ ShardId("shard-0".to_string()),
457
+ ShardId("shard-1".to_string()),
458
+ ];
439
459
  manager.initialize_shards(shards, HashMap::new());
440
460
 
441
461
  let shard = manager.get_shard_for_key("user123");
@@ -510,7 +530,13 @@ mod tests {
510
530
  manager.initialize_shards(shards, HashMap::new());
511
531
 
512
532
  // Create severe imbalanced load across 3 shards
513
- manager.record_shard_operation(&ShardId("shard-0".to_string()), "write", 5.0, 100000, 50000000);
533
+ manager.record_shard_operation(
534
+ &ShardId("shard-0".to_string()),
535
+ "write",
536
+ 5.0,
537
+ 100000,
538
+ 50000000,
539
+ );
514
540
  manager.record_shard_operation(&ShardId("shard-1".to_string()), "write", 5.0, 1000, 500000);
515
541
  manager.record_shard_operation(&ShardId("shard-2".to_string()), "write", 5.0, 100, 50000);
516
542