@feltdb/core 0.4.12 → 0.4.14

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 (165) hide show
  1. package/dist/cli/commands.js +42 -25
  2. package/dist/cli/index.js +1 -1
  3. package/dist/create/cli.js +39 -4
  4. package/dist/create/create.js +30 -18
  5. package/dist/create/docker-compose-generator.js +68 -11
  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/ConflictExplorer.d.ts.map +1 -1
  160. package/dist/studio/components/index.js +1 -1
  161. package/dist/studio/{components-Q0Nx6gLE.js → components-9kDSWiGL.js} +163 -47
  162. package/dist/studio/index.js +31 -28
  163. package/dist/studio-app/assets/{index-BHOmLZF-.js → index-DVdvmf69.js} +9 -9
  164. package/dist/studio-app/index.html +1 -1
  165. package/package.json +1 -1
@@ -0,0 +1,366 @@
1
+ /// TCP-based replication transport
2
+ ///
3
+ /// Implements ProtocolTransport over real TCP sockets using message framing.
4
+ ///
5
+ /// Wire Format: serde_json
6
+ /// - Chosen for compatibility with Operation::command.fields (serde_json::Value)
7
+ /// - bincode incompatible with untagged enums used by serde_json internally
8
+ /// - JSON is self-describing and provides stable framing for protocol evolution
9
+ /// - Length-prefix framing: 4-byte big-endian length + JSON payload
10
+ ///
11
+ /// Transport Guarantees:
12
+ /// - TCP connection establishment/closure
13
+ /// - Message framing (length prefix + payload)
14
+ /// - Ordered delivery within a single TCP connection (TCP's byte-stream ordering)
15
+ /// - Serialization integrity (JSON encoder/decoder with bincode-compatible semantics)
16
+ /// - Connection state tracking (connect, disconnect, is_connected)
17
+ /// - Bounded buffers (prevent unbounded growth)
18
+ ///
19
+ /// Deduplication/idempotency/retry logic is the protocol's responsibility via DistributedTransactionExecutor.
20
+
21
+ use crate::distributed_transactions::ReplicationMessage;
22
+ use crate::replication_protocol::{ProtocolError, ProtocolMetrics, ProtocolTransport};
23
+ use std::sync::atomic::{AtomicBool, Ordering};
24
+ use std::sync::Arc;
25
+ use tokio::io::{AsyncReadExt, AsyncWriteExt};
26
+ use tokio::net::{TcpListener, TcpStream};
27
+ use tokio::sync::Mutex;
28
+
29
+ const MESSAGE_BUFFER_SIZE: usize = 100;
30
+
31
+ /// TCP-based transport for ReplicationMessage
32
+ #[derive(Clone)]
33
+ pub struct TcpTransport {
34
+ local_addr: String,
35
+ peer_addr: Arc<Mutex<Option<String>>>,
36
+ stream: Arc<Mutex<Option<TcpStream>>>,
37
+ metrics: Arc<ProtocolMetrics>,
38
+ is_connected: Arc<AtomicBool>,
39
+ receive_buffer: Arc<Mutex<Vec<ReplicationMessage>>>,
40
+ }
41
+
42
+ impl TcpTransport {
43
+ /// Create a new TCP transport that will listen on the given address
44
+ pub fn new(local_addr: String) -> Self {
45
+ Self {
46
+ local_addr,
47
+ peer_addr: Arc::new(Mutex::new(None)),
48
+ stream: Arc::new(Mutex::new(None)),
49
+ metrics: Arc::new(ProtocolMetrics::new()),
50
+ is_connected: Arc::new(AtomicBool::new(false)),
51
+ receive_buffer: Arc::new(Mutex::new(Vec::with_capacity(MESSAGE_BUFFER_SIZE))),
52
+ }
53
+ }
54
+
55
+ /// Listen for incoming TCP connections
56
+ pub async fn listen(&mut self) -> Result<(), ProtocolError> {
57
+ let listener = TcpListener::bind(&self.local_addr)
58
+ .await
59
+ .map_err(|e| ProtocolError::ConnectionError(e.to_string()))?;
60
+
61
+ let stream = listener
62
+ .accept()
63
+ .await
64
+ .map_err(|e| ProtocolError::ConnectionError(e.to_string()))?
65
+ .0;
66
+
67
+ *self.stream.lock().await = Some(stream);
68
+ self.is_connected.store(true, Ordering::Relaxed);
69
+ self.metrics.record_connection_state_change();
70
+
71
+ Ok(())
72
+ }
73
+
74
+ pub fn metrics(&self) -> &ProtocolMetrics {
75
+ &self.metrics
76
+ }
77
+ }
78
+
79
+ #[async_trait::async_trait]
80
+ impl ProtocolTransport for TcpTransport {
81
+ async fn send(&self, message: ReplicationMessage) -> Result<(), ProtocolError> {
82
+ let mut stream_guard = self.stream.lock().await;
83
+ let stream = stream_guard
84
+ .as_mut()
85
+ .ok_or(ProtocolError::ConnectionError("not connected".to_string()))?;
86
+
87
+ // Serialize message using serde_json (bincode has issues with serde_json::Value)
88
+ let payload = serde_json::to_vec(&message)
89
+ .map_err(|e| ProtocolError::SerializationError(e.to_string()))?;
90
+
91
+ let payload_len = payload.len() as u32;
92
+
93
+ // Send length prefix (4 bytes, big-endian)
94
+ stream
95
+ .write_all(&payload_len.to_be_bytes())
96
+ .await
97
+ .map_err(|e| ProtocolError::TransportError(e.to_string()))?;
98
+
99
+ // Send payload
100
+ stream
101
+ .write_all(&payload)
102
+ .await
103
+ .map_err(|e| ProtocolError::TransportError(e.to_string()))?;
104
+
105
+ stream
106
+ .flush()
107
+ .await
108
+ .map_err(|e| ProtocolError::TransportError(e.to_string()))?;
109
+
110
+ self.metrics.record_send(4 + payload.len());
111
+
112
+ Ok(())
113
+ }
114
+
115
+ async fn receive(&self) -> Result<Vec<ReplicationMessage>, ProtocolError> {
116
+ let mut buffer = self.receive_buffer.lock().await;
117
+
118
+ // If we have buffered messages, return them
119
+ if !buffer.is_empty() {
120
+ let messages = std::mem::take(&mut *buffer);
121
+ return Ok(messages);
122
+ }
123
+
124
+ // Try to receive one message from the socket
125
+ let mut stream_guard = self.stream.lock().await;
126
+ let stream = stream_guard
127
+ .as_mut()
128
+ .ok_or(ProtocolError::ConnectionError("not connected".to_string()))?;
129
+
130
+ // Set non-blocking read
131
+ let mut len_bytes = [0u8; 4];
132
+ match stream.read_exact(&mut len_bytes).await {
133
+ Ok(0) => {
134
+ // Connection closed
135
+ return Err(ProtocolError::ConnectionError(
136
+ "connection closed by peer".to_string(),
137
+ ));
138
+ }
139
+ Ok(_) => {
140
+ let payload_len = u32::from_be_bytes(len_bytes) as usize;
141
+
142
+ if payload_len > 1024 * 1024 {
143
+ // Sanity check: don't allow messages larger than 1MB
144
+ return Err(ProtocolError::TransportError(
145
+ "message too large".to_string(),
146
+ ));
147
+ }
148
+
149
+ let mut payload = vec![0u8; payload_len];
150
+ stream
151
+ .read_exact(&mut payload)
152
+ .await
153
+ .map_err(|e| ProtocolError::TransportError(e.to_string()))?;
154
+
155
+ let message: ReplicationMessage = serde_json::from_slice(&payload)
156
+ .map_err(|e| ProtocolError::SerializationError(e.to_string()))?;
157
+
158
+ self.metrics.record_receive(4 + payload_len);
159
+
160
+ Ok(vec![message])
161
+ }
162
+ Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
163
+ // No data available right now
164
+ Ok(Vec::new())
165
+ }
166
+ Err(e) => Err(ProtocolError::TransportError(e.to_string())),
167
+ }
168
+ }
169
+
170
+ async fn connect(&mut self, peer_addr: &str) -> Result<(), ProtocolError> {
171
+ let stream = TcpStream::connect(peer_addr)
172
+ .await
173
+ .map_err(|e| ProtocolError::ConnectionError(e.to_string()))?;
174
+
175
+ *self.stream.lock().await = Some(stream);
176
+ *self.peer_addr.lock().await = Some(peer_addr.to_string());
177
+ self.is_connected.store(true, Ordering::Relaxed);
178
+ self.metrics.record_connection_state_change();
179
+
180
+ Ok(())
181
+ }
182
+
183
+ async fn disconnect(&mut self) -> Result<(), ProtocolError> {
184
+ *self.stream.lock().await = None;
185
+ self.is_connected.store(false, Ordering::Relaxed);
186
+ self.metrics.record_connection_state_change();
187
+
188
+ Ok(())
189
+ }
190
+
191
+ fn is_connected(&self) -> bool {
192
+ self.is_connected.load(Ordering::Relaxed)
193
+ }
194
+ }
195
+
196
+ #[cfg(test)]
197
+ mod tests {
198
+ use super::*;
199
+ use tokio::task;
200
+
201
+ #[tokio::test]
202
+ async fn tcp_bidirectional_message_exchange() {
203
+ let server_addr = "127.0.0.1:19001";
204
+
205
+ let mut server = TcpTransport::new(server_addr.to_string());
206
+ let mut client = TcpTransport::new("127.0.0.1:19002".to_string());
207
+
208
+ // Spawn server listening task
209
+ let _server_handle = {
210
+ let mut srv = server.clone();
211
+ task::spawn(async move {
212
+ srv.listen().await.expect("listen");
213
+ })
214
+ };
215
+
216
+ // Give server time to start listening
217
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
218
+
219
+ // Client connects
220
+ client
221
+ .connect(server_addr)
222
+ .await
223
+ .expect("client connect");
224
+
225
+ // Wait for server to process connection
226
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
227
+
228
+ // Create a test message
229
+ let msg = ReplicationMessage::new(
230
+ crate::distributed_transactions::TransactionEnvelope::new(
231
+ "test_node".to_string(),
232
+ 1,
233
+ "tx-1".to_string(),
234
+ vec![],
235
+ crate::transactions::ConsistencyContract::local(),
236
+ ),
237
+ "test_node".to_string(),
238
+ "peer_node".to_string(),
239
+ 1,
240
+ );
241
+
242
+ // Client sends
243
+ client.send(msg.clone()).await.expect("send");
244
+
245
+ // Server receives (wait briefly for message to arrive)
246
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
247
+ let received = server.receive().await.expect("receive");
248
+
249
+ println!("Server received {} messages", received.len());
250
+ assert_eq!(received.len(), 1);
251
+ assert_eq!(received[0].from_node, "test_node");
252
+ assert_eq!(received[0].to_node, "peer_node");
253
+
254
+ // Now try bidirectional: server sends back to client
255
+ let response = ReplicationMessage::new(
256
+ crate::distributed_transactions::TransactionEnvelope::new(
257
+ "server_node".to_string(),
258
+ 1,
259
+ "tx-2".to_string(),
260
+ vec![],
261
+ crate::transactions::ConsistencyContract::local(),
262
+ ),
263
+ "server_node".to_string(),
264
+ "client_node".to_string(),
265
+ 1,
266
+ );
267
+
268
+ server.send(response.clone()).await.expect("server send");
269
+
270
+ // Client receives (wait briefly for message to arrive)
271
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
272
+ let client_received = client.receive().await.expect("client receive");
273
+
274
+ println!("Client received {} messages", client_received.len());
275
+ assert_eq!(client_received.len(), 1);
276
+ assert_eq!(client_received[0].from_node, "server_node");
277
+ }
278
+
279
+ #[tokio::test]
280
+ async fn tcp_connection_status_tracked() {
281
+ let mut transport = TcpTransport::new("127.0.0.1:19003".to_string());
282
+
283
+ assert!(!transport.is_connected());
284
+
285
+ transport
286
+ .connect("127.0.0.1:9999")
287
+ .await
288
+ .expect_err("should fail - nobody listening");
289
+
290
+ assert!(!transport.is_connected());
291
+ assert_eq!(transport.metrics().get_connection_state_changes(), 0);
292
+ }
293
+
294
+ #[test]
295
+ fn bincode_serialization_roundtrip() {
296
+ let msg = ReplicationMessage::new(
297
+ crate::distributed_transactions::TransactionEnvelope::new(
298
+ "test_node".to_string(),
299
+ 1,
300
+ "tx-1".to_string(),
301
+ vec![],
302
+ crate::transactions::ConsistencyContract::local(),
303
+ ),
304
+ "test_node".to_string(),
305
+ "peer_node".to_string(),
306
+ 1,
307
+ );
308
+
309
+ let serialized = serde_json::to_vec(&msg).expect("serialize");
310
+ let deserialized: ReplicationMessage = serde_json::from_slice(&serialized).expect("deserialize");
311
+
312
+ assert_eq!(msg.from_node, deserialized.from_node);
313
+ assert_eq!(msg.to_node, deserialized.to_node);
314
+ assert_eq!(msg.sequence_number, deserialized.sequence_number);
315
+ }
316
+
317
+ #[test]
318
+ fn bincode_serialization_with_operation() {
319
+ use crate::convergence::VectorClock;
320
+ use crate::transactions::{Operation, OperationCommand, OperationId, StateVersion};
321
+ use std::collections::HashMap;
322
+ use serde_json::json;
323
+
324
+ let mut fields = HashMap::new();
325
+ fields.insert("key1".to_string(), json!("value1"));
326
+
327
+ let mut parent_vc = VectorClock::new();
328
+ parent_vc.increment("node_a");
329
+ let parent_version = StateVersion::new(parent_vc, "hash_initial_a".to_string());
330
+
331
+ let op = Operation::new(
332
+ OperationId::new("node_a".to_string(), 1),
333
+ parent_version.clone(),
334
+ "set_operation".to_string(),
335
+ OperationCommand {
336
+ op_type: "set".to_string(),
337
+ collection: "items".to_string(),
338
+ record_id: "item1".to_string(),
339
+ fields,
340
+ },
341
+ "node_a".to_string(),
342
+ );
343
+
344
+ let msg = ReplicationMessage::new(
345
+ crate::distributed_transactions::TransactionEnvelope::new(
346
+ "node_a".to_string(),
347
+ 1,
348
+ "tx-1".to_string(),
349
+ vec![op],
350
+ crate::transactions::ConsistencyContract::local(),
351
+ ),
352
+ "node_a".to_string(),
353
+ "node_b".to_string(),
354
+ 1,
355
+ );
356
+
357
+ let serialized = serde_json::to_vec(&msg).expect("serialize");
358
+ println!("Serialized {} bytes", serialized.len());
359
+
360
+ let deserialized: ReplicationMessage = serde_json::from_slice(&serialized).expect("deserialize");
361
+
362
+ assert_eq!(msg.from_node, deserialized.from_node);
363
+ assert_eq!(msg.to_node, deserialized.to_node);
364
+ assert_eq!(deserialized.envelope.operations.len(), 1);
365
+ }
366
+ }