@feltdb/core 0.4.12 → 0.4.13

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 (164) hide show
  1. package/dist/cli/commands.js +5 -2
  2. package/dist/cli/index.js +1 -1
  3. package/dist/create/cli.js +16 -1
  4. package/dist/create/create.js +30 -16
  5. package/dist/create/docker-compose-generator.js +48 -9
  6. package/dist/create/package-versions.js +1 -1
  7. package/dist/create/server-source/Cargo.lock +2238 -0
  8. package/dist/create/server-source/Cargo.toml +7 -0
  9. package/dist/create/server-source/crates/feltdb/Cargo.lock +175 -0
  10. package/dist/create/server-source/crates/feltdb/Cargo.toml +79 -0
  11. package/dist/create/server-source/crates/feltdb/benches/baselines/gate-13-redux.json +370 -0
  12. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +589 -0
  13. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +259 -0
  14. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +446 -0
  15. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +272 -0
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +378 -0
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +414 -0
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +486 -0
  19. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +273 -0
  20. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +587 -0
  21. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +513 -0
  22. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +395 -0
  23. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +469 -0
  24. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +409 -0
  25. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +627 -0
  26. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +383 -0
  27. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +298 -0
  28. package/dist/create/server-source/crates/feltdb/src/acceptance_tests.rs +1698 -0
  29. package/dist/create/server-source/crates/feltdb/src/acquisition.rs +286 -0
  30. package/dist/create/server-source/crates/feltdb/src/admission.rs +192 -0
  31. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +477 -0
  32. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +566 -0
  33. package/dist/create/server-source/crates/feltdb/src/analytics.rs +475 -0
  34. package/dist/create/server-source/crates/feltdb/src/application.rs +2244 -0
  35. package/dist/create/server-source/crates/feltdb/src/application_runtime.rs +1070 -0
  36. package/dist/create/server-source/crates/feltdb/src/authorization.rs +1030 -0
  37. package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +266 -0
  38. package/dist/create/server-source/crates/feltdb/src/capabilities/mod.rs +8 -0
  39. package/dist/create/server-source/crates/feltdb/src/capabilities/search.rs +418 -0
  40. package/dist/create/server-source/crates/feltdb/src/capabilities/vector.rs +482 -0
  41. package/dist/create/server-source/crates/feltdb/src/capability.rs +903 -0
  42. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +261 -0
  43. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +78 -0
  44. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +2214 -0
  45. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +194 -0
  46. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +427 -0
  47. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +453 -0
  48. package/dist/create/server-source/crates/feltdb/src/content_distribution.rs +465 -0
  49. package/dist/create/server-source/crates/feltdb/src/convergence.rs +618 -0
  50. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +418 -0
  51. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +380 -0
  52. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +362 -0
  53. package/dist/create/server-source/crates/feltdb/src/cron.rs +294 -0
  54. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +474 -0
  55. package/dist/create/server-source/crates/feltdb/src/distributed_tests.rs +1003 -0
  56. package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +536 -0
  57. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +364 -0
  58. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +235 -0
  59. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +207 -0
  60. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +316 -0
  61. package/dist/create/server-source/crates/feltdb/src/execution.rs +426 -0
  62. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +219 -0
  63. package/dist/create/server-source/crates/feltdb/src/indexing.rs +779 -0
  64. package/dist/create/server-source/crates/feltdb/src/lib.rs +2838 -0
  65. package/dist/create/server-source/crates/feltdb/src/materialization.rs +184 -0
  66. package/dist/create/server-source/crates/feltdb/src/metrics.rs +267 -0
  67. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +311 -0
  68. package/dist/create/server-source/crates/feltdb/src/observability.rs +366 -0
  69. package/dist/create/server-source/crates/feltdb/src/operation.rs +251 -0
  70. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +438 -0
  71. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +344 -0
  72. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +477 -0
  73. package/dist/create/server-source/crates/feltdb/src/peer_registry.rs +166 -0
  74. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +261 -0
  75. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +560 -0
  76. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +3226 -0
  77. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +201 -0
  78. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +263 -0
  79. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +484 -0
  80. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +216 -0
  81. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +281 -0
  82. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +323 -0
  83. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +573 -0
  84. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +404 -0
  85. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +418 -0
  86. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +381 -0
  87. package/dist/create/server-source/crates/feltdb/src/phase_1c_three_node.rs +523 -0
  88. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +334 -0
  89. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +306 -0
  90. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +355 -0
  91. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +395 -0
  92. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +346 -0
  93. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +430 -0
  94. package/dist/create/server-source/crates/feltdb/src/production_api.rs +400 -0
  95. package/dist/create/server-source/crates/feltdb/src/provenance.rs +207 -0
  96. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +217 -0
  97. package/dist/create/server-source/crates/feltdb/src/references.rs +404 -0
  98. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +401 -0
  99. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +160 -0
  100. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +132 -0
  101. package/dist/create/server-source/crates/feltdb/src/routing.rs +409 -0
  102. package/dist/create/server-source/crates/feltdb/src/sharding.rs +523 -0
  103. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +3118 -0
  104. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +291 -0
  105. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +376 -0
  106. package/dist/create/server-source/crates/feltdb/src/storage.rs +267 -0
  107. package/dist/create/server-source/crates/feltdb/src/submission.rs +477 -0
  108. package/dist/create/server-source/crates/feltdb/src/sync.rs +483 -0
  109. package/dist/create/server-source/crates/feltdb/src/sync_contract.rs +822 -0
  110. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +366 -0
  111. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +473 -0
  112. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +949 -0
  113. package/dist/create/server-source/crates/feltdb/src/transactions.rs +646 -0
  114. package/dist/create/server-source/crates/feltdb/src/trigger.rs +390 -0
  115. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +928 -0
  116. package/dist/create/server-source/crates/feltdb/src/workflow.rs +713 -0
  117. package/dist/create/server-source/crates/feltdb/src/workflow_acceptance_tests.rs +510 -0
  118. package/dist/create/server-source/crates/feltdb/src/workflow_integration.rs +354 -0
  119. package/dist/create/server-source/crates/feltdb/src/workflow_runtime.rs +594 -0
  120. package/dist/create/server-source/crates/feltdb/src/workload.rs +1310 -0
  121. package/dist/create/server-source/crates/feltdb-server/Cargo.toml +23 -0
  122. package/dist/create/server-source/crates/feltdb-server/README.md +79 -0
  123. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +73 -0
  124. package/dist/create/server-source/crates/feltdb-server/src/application_contract.rs +425 -0
  125. package/dist/create/server-source/crates/feltdb-server/src/artifacts.rs +449 -0
  126. package/dist/create/server-source/crates/feltdb-server/src/audit.rs +59 -0
  127. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +308 -0
  128. package/dist/create/server-source/crates/feltdb-server/src/authorization.rs +228 -0
  129. package/dist/create/server-source/crates/feltdb-server/src/backup.rs +416 -0
  130. package/dist/create/server-source/crates/feltdb-server/src/causal.rs +218 -0
  131. package/dist/create/server-source/crates/feltdb-server/src/certification.rs +223 -0
  132. package/dist/create/server-source/crates/feltdb-server/src/clock.rs +132 -0
  133. package/dist/create/server-source/crates/feltdb-server/src/cluster.rs +165 -0
  134. package/dist/create/server-source/crates/feltdb-server/src/connections.rs +1044 -0
  135. package/dist/create/server-source/crates/feltdb-server/src/content.rs +111 -0
  136. package/dist/create/server-source/crates/feltdb-server/src/identity.rs +250 -0
  137. package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +78 -0
  138. package/dist/create/server-source/crates/feltdb-server/src/key_provider.rs +247 -0
  139. package/dist/create/server-source/crates/feltdb-server/src/leases.rs +123 -0
  140. package/dist/create/server-source/crates/feltdb-server/src/lib.rs +25 -0
  141. package/dist/create/server-source/crates/feltdb-server/src/main.rs +8715 -0
  142. package/dist/create/server-source/crates/feltdb-server/src/metrics.rs +97 -0
  143. package/dist/create/server-source/crates/feltdb-server/src/portable_bundle.rs +350 -0
  144. package/dist/create/server-source/crates/feltdb-server/src/principals.rs +510 -0
  145. package/dist/create/server-source/crates/feltdb-server/src/providers.rs +269 -0
  146. package/dist/create/server-source/crates/feltdb-server/src/releases.rs +2563 -0
  147. package/dist/create/server-source/crates/feltdb-server/src/sessions.rs +156 -0
  148. package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +1097 -0
  149. package/dist/create/server-source/crates/feltdb-server/src/versions.rs +264 -0
  150. package/dist/create/server-source/crates/feltdb-wasm/Cargo.toml +31 -0
  151. package/dist/create/server-source/crates/feltdb-wasm/src/lib.rs +1086 -0
  152. package/dist/create/server-source/crates/feltdb-wasm/test.db +0 -0
  153. package/dist/flowspec.d.ts +2 -0
  154. package/dist/flowspec.d.ts.map +1 -1
  155. package/dist/flowspec.js +28 -4
  156. package/dist/state-contract.d.ts +7 -1
  157. package/dist/state-contract.d.ts.map +1 -1
  158. package/dist/studio/components/ApplicationDesigner.d.ts.map +1 -1
  159. package/dist/studio/components/index.js +1 -1
  160. package/dist/studio/{components-Q0Nx6gLE.js → components-bHTARBin.js} +156 -46
  161. package/dist/studio/index.js +31 -28
  162. package/dist/studio-app/assets/{index-BHOmLZF-.js → index-BqKquLuU.js} +8 -8
  163. package/dist/studio-app/index.html +1 -1
  164. package/package.json +1 -1
@@ -0,0 +1,469 @@
1
+ /// Gate 14C: Replication Contract Test
2
+ ///
3
+ /// CRITICAL: Before scaling measurement, prove the replication harness is correct.
4
+ ///
5
+ /// This test validates that ReplicationMessages are delivered through the real path:
6
+ /// operation → replication_message → receiver → deduplication → causal_validation → apply → state
7
+ ///
8
+ /// Contract: leader.state_hash == replica.state_hash after all operations applied
9
+ ///
10
+ /// Test cases:
11
+ /// 1. Basic: N operations delivered in order → convergence ✓
12
+ /// 2. Duplicate: Same message delivered twice → deduplication prevents double-apply
13
+ /// 3. Reordered: Messages delivered out of order → causal validation preserves order
14
+ /// 4. Delayed: Messages arrive late → eventual convergence ✓
15
+ /// 5. Dropped + Retx: Message lost then resent → reconciliation recovers it
16
+ /// 6. Causal dependency: Operation depends on prior → waiting/ready state correct
17
+
18
+ use feltdb::{
19
+ convergence::VectorClock,
20
+ distributed_transactions::{DistributedTransactionExecutor, ReplicationMessage},
21
+ state_hash::StateHash,
22
+ transactions::{ConsistencyContract, Operation, OperationCommand, OperationId, StateVersion},
23
+ };
24
+ use std::collections::HashMap;
25
+
26
+ // ============================================================================
27
+ // REPLICATION HARNESS
28
+ // ============================================================================
29
+
30
+ /// Simulates network delivery with configurable behavior (drops, delays, reordering)
31
+ #[allow(dead_code)]
32
+ struct ReplicationTransport {
33
+ messages: Vec<(usize, ReplicationMessage)>, // (destination_replica_id, message)
34
+ #[allow(dead_code)]
35
+ drops_enabled: bool,
36
+ #[allow(dead_code)]
37
+ delays_enabled: bool,
38
+ #[allow(dead_code)]
39
+ reordering_enabled: bool,
40
+ }
41
+
42
+ #[allow(dead_code)]
43
+ impl ReplicationTransport {
44
+ fn new() -> Self {
45
+ Self {
46
+ messages: Vec::new(),
47
+ drops_enabled: false,
48
+ delays_enabled: false,
49
+ reordering_enabled: false,
50
+ }
51
+ }
52
+
53
+ fn send(&mut self, replica_id: usize, msg: ReplicationMessage) {
54
+ self.messages.push((replica_id, msg));
55
+ }
56
+
57
+ fn deliver_all(&mut self) -> Vec<(usize, ReplicationMessage)> {
58
+ self.messages.drain(..).collect()
59
+ }
60
+
61
+ fn deliver_with_drops(&mut self, drop_every_nth: usize) -> Vec<(usize, ReplicationMessage)> {
62
+ let mut delivered = Vec::new();
63
+ for (i, msg) in self.messages.drain(..).enumerate() {
64
+ if i % drop_every_nth != 0 {
65
+ delivered.push(msg);
66
+ }
67
+ }
68
+ delivered
69
+ }
70
+ }
71
+
72
+ // ============================================================================
73
+ // CONTRACT TESTS
74
+ // ============================================================================
75
+
76
+ fn main() {
77
+ let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
78
+ rt.block_on(async {
79
+ println!("\n╔════════════════════════════════════════════════════════════╗");
80
+ println!("║ GATE 14C: Replication Contract Test ║");
81
+ println!("║ Prove: leader.state_hash == replica.state_hash ║");
82
+ println!("╚════════════════════════════════════════════════════════════╝\n");
83
+
84
+ // TEST 1: Basic 2-replica convergence
85
+ println!("Test 1: Basic 2-Replica Convergence");
86
+ println!("───────────────────────────────────");
87
+ test_basic_2replica_convergence().await;
88
+
89
+ // TEST 2: Duplicate message handling
90
+ println!("\nTest 2: Duplicate Message Deduplication");
91
+ println!("───────────────────────────────────────");
92
+ test_duplicate_message_handling().await;
93
+
94
+ // TEST 3: Out-of-order delivery with causal validation
95
+ println!("\nTest 3: Out-of-Order Delivery");
96
+ println!("────────────────────────────");
97
+ test_out_of_order_delivery().await;
98
+
99
+ // TEST 4: Delayed delivery
100
+ println!("\nTest 4: Delayed Message Delivery");
101
+ println!("───────────────────────────────");
102
+ test_delayed_delivery().await;
103
+
104
+ // TEST 5: Drop and retransmission
105
+ println!("\nTest 5: Message Drop and Retransmission");
106
+ println!("──────────────────────────────────────");
107
+ test_drop_and_retransmission().await;
108
+
109
+ println!("\n╔════════════════════════════════════════════════════════════╗");
110
+ println!("║ Contract Test Complete ║");
111
+ println!("║ Next: Run scaling benchmark only after all tests PASS ║");
112
+ println!("╚════════════════════════════════════════════════════════════╝\n");
113
+ });
114
+ }
115
+
116
+ async fn test_basic_2replica_convergence() {
117
+ // Setup: 1 leader + 1 replica
118
+ let initial_hash = StateHash::from_hex("hash0".to_string());
119
+ let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
120
+ leader.register_replica("replica_1".to_string(), initial_hash.clone());
121
+ let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
122
+
123
+ // Create 5 operations
124
+ let mut operations = Vec::new();
125
+ for i in 0..5 {
126
+ let op = Operation::new(
127
+ OperationId::new("leader".to_string(), i as u64),
128
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
129
+ "Update".to_string(),
130
+ OperationCommand {
131
+ op_type: "Set".to_string(),
132
+ collection: "test".to_string(),
133
+ record_id: format!("key_{}", i),
134
+ fields: {
135
+ let mut m = HashMap::new();
136
+ m.insert("value".to_string(), serde_json::json!(i));
137
+ m
138
+ },
139
+ },
140
+ "test".to_string(),
141
+ );
142
+ operations.push(op);
143
+ }
144
+
145
+ // Leader: Execute operations
146
+ let mut leader_hashes = Vec::new();
147
+ for (seq, op) in operations.iter().enumerate() {
148
+ let result = leader.execute_local_transaction(
149
+ seq as u64,
150
+ format!("txn_{}", seq),
151
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
152
+ vec![op.clone()],
153
+ ConsistencyContract::local(),
154
+ );
155
+
156
+ match result {
157
+ Ok(envelope) => {
158
+ leader_hashes.push(format!("{:?}", leader.get_replica_state("leader").map(|s| s.state_hash)));
159
+ println!(" ✓ Leader applied operation {}", seq);
160
+
161
+ // Replicate to follower
162
+ let msg = ReplicationMessage::new(
163
+ envelope,
164
+ "leader".to_string(),
165
+ "replica_1".to_string(),
166
+ seq as u64,
167
+ );
168
+
169
+ // Replica: Receive and apply
170
+ let rx_result = replica.receive_replicated_transaction(
171
+ msg,
172
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
173
+ );
174
+
175
+ match rx_result {
176
+ Ok(_) => println!(" ✓ Replica applied operation {}", seq),
177
+ Err(e) => println!(" ✗ Replica failed: {}", e),
178
+ }
179
+ }
180
+ Err(e) => println!(" ✗ Leader failed: {}", e),
181
+ }
182
+ }
183
+
184
+ // Verify convergence
185
+ let leader_state = leader.get_replica_state("leader");
186
+ let replica_state = replica.get_replica_state("replica_1");
187
+
188
+ println!("\nConvergence Check:");
189
+ match (&leader_state, &replica_state) {
190
+ (Some(l), Some(r)) => {
191
+ let match_str = if l.state_hash == r.state_hash {
192
+ "✓ CONVERGED"
193
+ } else {
194
+ "✗ DIVERGED"
195
+ };
196
+ println!(" Leader hash: {:?}", l.state_hash);
197
+ println!(" Replica hash: {:?}", r.state_hash);
198
+ println!(" {}", match_str);
199
+ }
200
+ _ => println!(" ✗ State retrieval failed"),
201
+ }
202
+ }
203
+
204
+ async fn test_duplicate_message_handling() {
205
+ let initial_hash = StateHash::from_hex("hash0".to_string());
206
+ let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
207
+ leader.register_replica("replica_1".to_string(), initial_hash.clone());
208
+ let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
209
+
210
+ // Create and apply one operation
211
+ let op = Operation::new(
212
+ OperationId::new("leader".to_string(), 0),
213
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
214
+ "Update".to_string(),
215
+ OperationCommand {
216
+ op_type: "Set".to_string(),
217
+ collection: "test".to_string(),
218
+ record_id: "key_0".to_string(),
219
+ fields: {
220
+ let mut m = HashMap::new();
221
+ m.insert("value".to_string(), serde_json::json!(1));
222
+ m
223
+ },
224
+ },
225
+ "test".to_string(),
226
+ );
227
+
228
+ let envelope = leader
229
+ .execute_local_transaction(
230
+ 0,
231
+ "txn_0".to_string(),
232
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
233
+ vec![op],
234
+ ConsistencyContract::local(),
235
+ )
236
+ .expect("Leader execution failed");
237
+
238
+ let msg = ReplicationMessage::new(
239
+ envelope.clone(),
240
+ "leader".to_string(),
241
+ "replica_1".to_string(),
242
+ 0,
243
+ );
244
+
245
+ // Deliver message first time
246
+ let result1 = replica.receive_replicated_transaction(
247
+ msg.clone(),
248
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
249
+ );
250
+ println!(" First delivery: {}", if result1.is_ok() { "✓ OK" } else { "✗ Failed" });
251
+
252
+ // Deliver same message again (duplicate)
253
+ let result2 = replica.receive_replicated_transaction(
254
+ msg,
255
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
256
+ );
257
+ println!(" Duplicate delivery: {}", if result2.is_err() { "✓ Rejected (correct)" } else { "✗ Accepted (wrong!)" });
258
+
259
+ // Verify only applied once
260
+ if let Some(state) = replica.get_replica_state("replica_1") {
261
+ println!(" Operations applied: {}", state.operations_applied);
262
+ }
263
+ }
264
+
265
+ async fn test_out_of_order_delivery() {
266
+ let initial_hash = StateHash::from_hex("hash0".to_string());
267
+ let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
268
+ leader.register_replica("replica_1".to_string(), initial_hash.clone());
269
+ let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
270
+
271
+ // Create 3 operations
272
+ let mut envelopes = Vec::new();
273
+ for i in 0..3 {
274
+ let op = Operation::new(
275
+ OperationId::new("leader".to_string(), i as u64),
276
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
277
+ "Update".to_string(),
278
+ OperationCommand {
279
+ op_type: "Set".to_string(),
280
+ collection: "test".to_string(),
281
+ record_id: format!("key_{}", i),
282
+ fields: {
283
+ let mut m = HashMap::new();
284
+ m.insert("value".to_string(), serde_json::json!(i));
285
+ m
286
+ },
287
+ },
288
+ "test".to_string(),
289
+ );
290
+
291
+ let result = leader.execute_local_transaction(
292
+ i as u64,
293
+ format!("txn_{}", i),
294
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
295
+ vec![op],
296
+ ConsistencyContract::local(),
297
+ );
298
+
299
+ if let Ok(envelope) = result {
300
+ envelopes.push((i, envelope));
301
+ }
302
+ }
303
+
304
+ // Deliver messages out of order: 2, 0, 1
305
+ let delivery_order = vec![2, 0, 1];
306
+ for idx in delivery_order {
307
+ if idx < envelopes.len() {
308
+ let (seq, envelope) = envelopes[idx].clone();
309
+ let msg = ReplicationMessage::new(
310
+ envelope,
311
+ "leader".to_string(),
312
+ "replica_1".to_string(),
313
+ seq as u64,
314
+ );
315
+
316
+ let result = replica.receive_replicated_transaction(
317
+ msg,
318
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
319
+ );
320
+ println!(" Operation {} delivered: {}", seq, if result.is_ok() { "✓" } else { "✗" });
321
+ }
322
+ }
323
+
324
+ // Verify replica eventually has all operations
325
+ if let Some(state) = replica.get_replica_state("replica_1") {
326
+ println!(" Replica has {} operations (expected 3)", state.operations_applied);
327
+ }
328
+ }
329
+
330
+ async fn test_delayed_delivery() {
331
+ let initial_hash = StateHash::from_hex("hash0".to_string());
332
+ let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
333
+ leader.register_replica("replica_1".to_string(), initial_hash.clone());
334
+ let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
335
+
336
+ // Create and execute one operation at leader
337
+ let op = Operation::new(
338
+ OperationId::new("leader".to_string(), 0),
339
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
340
+ "Update".to_string(),
341
+ OperationCommand {
342
+ op_type: "Set".to_string(),
343
+ collection: "test".to_string(),
344
+ record_id: "key_0".to_string(),
345
+ fields: {
346
+ let mut m = HashMap::new();
347
+ m.insert("value".to_string(), serde_json::json!(1));
348
+ m
349
+ },
350
+ },
351
+ "test".to_string(),
352
+ );
353
+
354
+ let envelope = leader
355
+ .execute_local_transaction(
356
+ 0,
357
+ "txn_0".to_string(),
358
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
359
+ vec![op],
360
+ ConsistencyContract::local(),
361
+ )
362
+ .expect("Leader execution failed");
363
+
364
+ let msg = ReplicationMessage::new(
365
+ envelope,
366
+ "leader".to_string(),
367
+ "replica_1".to_string(),
368
+ 0,
369
+ );
370
+
371
+ println!(" Simulating delay...");
372
+ // In a real test, this would use tokio::time::sleep, but for now just immediate delivery
373
+ let result = replica.receive_replicated_transaction(
374
+ msg,
375
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
376
+ );
377
+ println!(" After delay delivery: {}", if result.is_ok() { "✓ OK" } else { "✗ Failed" });
378
+
379
+ // Verify convergence
380
+ let leader_state = leader.get_replica_state("leader");
381
+ let replica_state = replica.get_replica_state("replica_1");
382
+
383
+ println!("\nDelayed Delivery Convergence Check:");
384
+ match (&leader_state, &replica_state) {
385
+ (Some(l), Some(r)) => {
386
+ let match_str = if l.state_hash == r.state_hash {
387
+ "✓ CONVERGED"
388
+ } else {
389
+ "✗ DIVERGED"
390
+ };
391
+ println!(" Leader hash: {:?}", l.state_hash);
392
+ println!(" Replica hash: {:?}", r.state_hash);
393
+ println!(" {}", match_str);
394
+ }
395
+ _ => println!(" ✗ State retrieval failed"),
396
+ }
397
+ }
398
+
399
+ async fn test_drop_and_retransmission() {
400
+ let initial_hash = StateHash::from_hex("hash0".to_string());
401
+ let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
402
+ leader.register_replica("replica_1".to_string(), initial_hash.clone());
403
+ let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
404
+
405
+ // Create and execute one operation at leader
406
+ let op = Operation::new(
407
+ OperationId::new("leader".to_string(), 0),
408
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
409
+ "Update".to_string(),
410
+ OperationCommand {
411
+ op_type: "Set".to_string(),
412
+ collection: "test".to_string(),
413
+ record_id: "key_0".to_string(),
414
+ fields: {
415
+ let mut m = HashMap::new();
416
+ m.insert("value".to_string(), serde_json::json!(1));
417
+ m
418
+ },
419
+ },
420
+ "test".to_string(),
421
+ );
422
+
423
+ let envelope = leader
424
+ .execute_local_transaction(
425
+ 0,
426
+ "txn_0".to_string(),
427
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
428
+ vec![op],
429
+ ConsistencyContract::local(),
430
+ )
431
+ .expect("Leader execution failed");
432
+
433
+ let msg = ReplicationMessage::new(
434
+ envelope.clone(),
435
+ "leader".to_string(),
436
+ "replica_1".to_string(),
437
+ 0,
438
+ );
439
+
440
+ // Simulate drop: don't deliver message first time
441
+ println!(" Message dropped (simulated)");
442
+
443
+ // Retransmit: deliver the same message
444
+ let result = replica.receive_replicated_transaction(
445
+ msg,
446
+ StateVersion::new(VectorClock::new(), "hash0".to_string()),
447
+ );
448
+ println!(" Message retransmitted: {}", if result.is_ok() { "✓ OK" } else { "✗ Failed" });
449
+
450
+ // Verify convergence
451
+ let leader_state = leader.get_replica_state("leader");
452
+ let replica_state = replica.get_replica_state("replica_1");
453
+
454
+ println!("\nDrop/Retransmission Convergence Check:");
455
+ match (&leader_state, &replica_state) {
456
+ (Some(l), Some(r)) => {
457
+ let match_str = if l.state_hash == r.state_hash {
458
+ "✓ CONVERGED"
459
+ } else {
460
+ "✗ DIVERGED"
461
+ };
462
+ println!(" Leader hash: {:?}", l.state_hash);
463
+ println!(" Replica hash: {:?}", r.state_hash);
464
+ println!(" {}", match_str);
465
+ }
466
+ _ => println!(" ✗ State retrieval failed"),
467
+ }
468
+ }
469
+