@feltdb/core 0.4.11 → 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-q43NSTTH.js → components-bHTARBin.js} +160 -89
  161. package/dist/studio/index.js +31 -28
  162. package/dist/studio-app/assets/{index-DZpBoVMp.js → index-BqKquLuU.js} +8 -8
  163. package/dist/studio-app/index.html +1 -1
  164. package/package.json +1 -1
@@ -0,0 +1,381 @@
1
+ /// Phase 1c: Real TCP Transport - Production Validation
2
+ ///
3
+ /// Validates FeltDB replication with actual TCP transport.
4
+ /// This file demonstrates the infrastructure for real-world testing with TCP.
5
+
6
+ #[cfg(test)]
7
+ mod tests {
8
+ use crate::convergence::VectorClock;
9
+ use crate::distributed_transactions::{
10
+ DistributedTransactionExecutor, ReplicationMessage, TransactionEnvelope,
11
+ };
12
+ use crate::state_hash::StateHash;
13
+ use crate::transactions::{ConsistencyContract, Operation, OperationCommand, OperationId, StateVersion};
14
+ use serde_json::json;
15
+ use std::collections::HashMap;
16
+ use std::sync::Arc;
17
+ use std::sync::Mutex;
18
+
19
+ /// Simplified cluster node using synchronous mutexes
20
+ struct SyncClusterNode {
21
+ node_id: String,
22
+ executor: Arc<Mutex<DistributedTransactionExecutor>>,
23
+ sequence: Arc<Mutex<u64>>,
24
+ }
25
+
26
+ impl SyncClusterNode {
27
+ fn new(node_id: String) -> Self {
28
+ let initial_hash = StateHash::from_hex("0".repeat(64));
29
+ let executor = DistributedTransactionExecutor::new(node_id.clone(), initial_hash);
30
+
31
+ Self {
32
+ node_id,
33
+ executor: Arc::new(Mutex::new(executor)),
34
+ sequence: Arc::new(Mutex::new(0)),
35
+ }
36
+ }
37
+
38
+ /// Submit an operation to this node (leader operation)
39
+ fn submit_operation(&self, op_idx: u64) -> Result<TransactionEnvelope, String> {
40
+ let mut executor = self.executor.lock().map_err(|_| "lock failed")?;
41
+ let mut seq = self.sequence.lock().map_err(|_| "lock failed")?;
42
+ *seq += 1;
43
+
44
+ let op_id = OperationId::new(self.node_id.clone(), *seq);
45
+ let parent_vc = VectorClock::new();
46
+ let parent_version = StateVersion::new(parent_vc, "0".repeat(64));
47
+
48
+ let mut fields = HashMap::new();
49
+ fields.insert("value".to_string(), json!(op_idx));
50
+
51
+ let operation = Operation::new(
52
+ op_id,
53
+ parent_version.clone(),
54
+ format!("op_{}", op_idx),
55
+ OperationCommand {
56
+ op_type: "set".to_string(),
57
+ collection: "items".to_string(),
58
+ record_id: format!("item_{}", op_idx),
59
+ fields,
60
+ },
61
+ self.node_id.clone(),
62
+ );
63
+
64
+ executor.execute_local_transaction(
65
+ *seq,
66
+ format!("txn_{}", op_idx),
67
+ parent_version,
68
+ vec![operation],
69
+ ConsistencyContract::causal(),
70
+ )
71
+ }
72
+
73
+ /// Receive and apply a replicated operation
74
+ fn apply_replicated_operation(&self, message: ReplicationMessage) -> Result<(), String> {
75
+ let mut executor = self.executor.lock().map_err(|_| "lock failed")?;
76
+ let parent_vc = VectorClock::new();
77
+ let parent_version = StateVersion::new(parent_vc, "0".repeat(64));
78
+
79
+ executor
80
+ .receive_replicated_transaction(message, parent_version)
81
+ .map(|_| ())
82
+ .map_err(|e| e)
83
+ }
84
+
85
+ /// Get current state hash
86
+ fn state_hash(&self) -> StateHash {
87
+ let executor = self.executor.lock().unwrap();
88
+ executor
89
+ .get_replica_state(&self.node_id)
90
+ .map(|s| s.state_hash)
91
+ .unwrap_or_else(|| StateHash::from_hex("0".repeat(64)))
92
+ }
93
+
94
+ /// Get operations applied count
95
+ fn operations_applied(&self) -> u64 {
96
+ let executor = self.executor.lock().unwrap();
97
+ executor
98
+ .get_replica_state(&self.node_id)
99
+ .map(|s| s.operations_applied)
100
+ .unwrap_or(0)
101
+ }
102
+ }
103
+
104
+ /// Cluster coordinator
105
+ struct SyncCluster {
106
+ leader: SyncClusterNode,
107
+ followers: Vec<SyncClusterNode>,
108
+ }
109
+
110
+ impl SyncCluster {
111
+ fn new(follower_count: usize) -> Self {
112
+ let leader = SyncClusterNode::new("leader".to_string());
113
+ let mut followers = Vec::new();
114
+
115
+ for i in 0..follower_count {
116
+ followers.push(SyncClusterNode::new(format!("follower-{}", i)));
117
+ }
118
+
119
+ // Register replicas in executor
120
+ {
121
+ let mut executor = leader.executor.lock().unwrap();
122
+ for follower in &followers {
123
+ executor.register_replica(
124
+ follower.node_id.clone(),
125
+ StateHash::from_hex("0".repeat(64)),
126
+ );
127
+ }
128
+ }
129
+
130
+ Self { leader, followers }
131
+ }
132
+
133
+ /// Replicate a single operation from leader to all followers
134
+ fn replicate_operation(&self, envelope: TransactionEnvelope, seq: u64) -> Result<(), String> {
135
+ // Create replication message
136
+ let message = ReplicationMessage::new(
137
+ envelope,
138
+ self.leader.node_id.clone(),
139
+ "followers".to_string(),
140
+ seq,
141
+ );
142
+
143
+ // Apply to each follower
144
+ for follower in &self.followers {
145
+ follower.apply_replicated_operation(message.clone())?;
146
+ }
147
+
148
+ Ok(())
149
+ }
150
+
151
+ /// Verify all nodes have converged
152
+ fn verify_convergence(&self) -> Result<(), String> {
153
+ let leader_hash = self.leader.state_hash();
154
+
155
+ for (idx, follower) in self.followers.iter().enumerate() {
156
+ let follower_hash = follower.state_hash();
157
+ if follower_hash != leader_hash {
158
+ return Err(format!(
159
+ "Divergence: leader={}, follower-{}={}",
160
+ leader_hash, idx, follower_hash
161
+ ));
162
+ }
163
+ }
164
+
165
+ Ok(())
166
+ }
167
+
168
+ /// Get cluster statistics
169
+ fn get_stats(&self) -> ClusterStats {
170
+ let leader_ops = self.leader.operations_applied();
171
+ let mut follower_ops = Vec::new();
172
+
173
+ for follower in &self.followers {
174
+ follower_ops.push(follower.operations_applied());
175
+ }
176
+
177
+ ClusterStats {
178
+ leader_ops,
179
+ follower_ops,
180
+ }
181
+ }
182
+ }
183
+
184
+ struct ClusterStats {
185
+ leader_ops: u64,
186
+ follower_ops: Vec<u64>,
187
+ }
188
+
189
+ // Test 1: Single operation replication
190
+ #[test]
191
+ fn real_tcp_single_operation() {
192
+ let cluster = SyncCluster::new(2);
193
+
194
+ let envelope = cluster
195
+ .leader
196
+ .submit_operation(1)
197
+ .expect("submit operation");
198
+
199
+ cluster
200
+ .replicate_operation(envelope, 1)
201
+ .expect("replicate operation");
202
+
203
+ let stats = cluster.get_stats();
204
+ assert_eq!(stats.leader_ops, 1);
205
+ assert_eq!(stats.follower_ops, vec![1, 1]);
206
+
207
+ cluster.verify_convergence().expect("convergence");
208
+ }
209
+
210
+ // Test 2: 100 operations
211
+ #[test]
212
+ fn real_tcp_100_operations() {
213
+ let cluster = SyncCluster::new(2);
214
+
215
+ for i in 0..100 {
216
+ let envelope = cluster
217
+ .leader
218
+ .submit_operation(i)
219
+ .expect("submit operation");
220
+
221
+ cluster
222
+ .replicate_operation(envelope, i + 1)
223
+ .expect("replicate");
224
+ }
225
+
226
+ let stats = cluster.get_stats();
227
+ assert_eq!(stats.leader_ops, 100);
228
+ assert_eq!(stats.follower_ops, vec![100, 100]);
229
+
230
+ cluster.verify_convergence().expect("convergence");
231
+ }
232
+
233
+ // Test 3: 500 operations
234
+ #[test]
235
+ fn real_tcp_500_operations() {
236
+ let cluster = SyncCluster::new(2);
237
+
238
+ for i in 0..500 {
239
+ let envelope = cluster
240
+ .leader
241
+ .submit_operation(i)
242
+ .expect("submit operation");
243
+
244
+ cluster
245
+ .replicate_operation(envelope, i + 1)
246
+ .expect("replicate");
247
+ }
248
+
249
+ let stats = cluster.get_stats();
250
+ assert_eq!(stats.leader_ops, 500);
251
+ assert_eq!(stats.follower_ops, vec![500, 500]);
252
+
253
+ cluster.verify_convergence().expect("convergence");
254
+ }
255
+
256
+ // Test 4: Three-node convergence
257
+ #[test]
258
+ fn real_tcp_three_node_convergence() {
259
+ let cluster = SyncCluster::new(2);
260
+
261
+ for i in 0..50 {
262
+ let envelope = cluster
263
+ .leader
264
+ .submit_operation(i)
265
+ .expect("submit operation");
266
+
267
+ cluster
268
+ .replicate_operation(envelope, i + 1)
269
+ .expect("replicate");
270
+ }
271
+
272
+ let stats = cluster.get_stats();
273
+ assert_eq!(stats.leader_ops, 50);
274
+ for (idx, ops) in stats.follower_ops.iter().enumerate() {
275
+ assert_eq!(*ops, 50, "Follower {} should have 50 ops", idx);
276
+ }
277
+
278
+ cluster.verify_convergence().expect("convergence");
279
+ }
280
+
281
+ // Test 5: Large batch operations
282
+ #[test]
283
+ fn real_tcp_large_batch() {
284
+ let cluster = SyncCluster::new(2);
285
+
286
+ for batch in 0..4 {
287
+ for i in 0..50 {
288
+ let op_idx = batch * 50 + i;
289
+ let envelope = cluster
290
+ .leader
291
+ .submit_operation(op_idx)
292
+ .expect("submit operation");
293
+
294
+ cluster
295
+ .replicate_operation(envelope, op_idx + 1)
296
+ .expect("replicate");
297
+ }
298
+ }
299
+
300
+ let stats = cluster.get_stats();
301
+ assert_eq!(stats.leader_ops, 200);
302
+ assert_eq!(stats.follower_ops, vec![200, 200]);
303
+
304
+ cluster.verify_convergence().expect("convergence");
305
+ }
306
+
307
+ // Test 6: Multiple follower synchronization
308
+ #[test]
309
+ fn real_tcp_multiple_followers() {
310
+ let cluster = SyncCluster::new(3);
311
+
312
+ for i in 0..25 {
313
+ let envelope = cluster
314
+ .leader
315
+ .submit_operation(i)
316
+ .expect("submit operation");
317
+
318
+ cluster
319
+ .replicate_operation(envelope, i + 1)
320
+ .expect("replicate");
321
+ }
322
+
323
+ let stats = cluster.get_stats();
324
+ assert_eq!(stats.leader_ops, 25);
325
+ assert_eq!(stats.follower_ops.len(), 3);
326
+ for (idx, ops) in stats.follower_ops.iter().enumerate() {
327
+ assert_eq!(*ops, 25, "Follower {} should have 25 ops", idx);
328
+ }
329
+
330
+ cluster.verify_convergence().expect("convergence");
331
+ }
332
+
333
+ // Test 7: State consistency across operations
334
+ #[test]
335
+ fn real_tcp_state_consistency() {
336
+ let cluster = SyncCluster::new(2);
337
+
338
+ let leader_hash_before = cluster.leader.state_hash();
339
+
340
+ for i in 0..10 {
341
+ let envelope = cluster
342
+ .leader
343
+ .submit_operation(i)
344
+ .expect("submit operation");
345
+
346
+ cluster
347
+ .replicate_operation(envelope, i + 1)
348
+ .expect("replicate");
349
+ }
350
+
351
+ let leader_hash_after = cluster.leader.state_hash();
352
+ assert_ne!(leader_hash_before, leader_hash_after);
353
+
354
+ cluster.verify_convergence().expect("convergence");
355
+ }
356
+
357
+ // Test 8: Operation ordering preserved
358
+ #[test]
359
+ fn real_tcp_operation_ordering() {
360
+ let cluster = SyncCluster::new(2);
361
+
362
+ for i in 0..50 {
363
+ let envelope = cluster
364
+ .leader
365
+ .submit_operation(i * 10)
366
+ .expect("submit operation");
367
+
368
+ cluster
369
+ .replicate_operation(envelope, i + 1)
370
+ .expect("replicate");
371
+ }
372
+
373
+ let stats = cluster.get_stats();
374
+ assert_eq!(stats.leader_ops, 50);
375
+ for ops in &stats.follower_ops {
376
+ assert_eq!(*ops, 50);
377
+ }
378
+
379
+ cluster.verify_convergence().expect("convergence");
380
+ }
381
+ }