Skip to content

Commit 59c477b

Browse files
mickvandijkeclaude
andcommitted
fix: remove duplicate receive loops by moving networking setup from new() to start()
P2PNode::new() and start() both called start_network_listeners() and start_message_receiving_system(), spawning duplicate accept and receive loops competing on the same QUIC endpoint. This caused messages to be randomly split between loops, leading to flaky delivery. Now new() only constructs the struct; start() is the single place where background loops are spawned. All callers updated to call start() after new(). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 49421d8 commit 59c477b

8 files changed

Lines changed: 77 additions & 14 deletions

examples/chat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ async fn main() -> Result<()> {
6464

6565
// Create and start the node
6666
let node = P2PNode::new(config).await?;
67+
node.start().await?;
6768

6869
// Handle bootstrap peers
6970
let mut bootstrap_addrs: Vec<Multiaddr> = Vec::new();

examples/test_network.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl TestNode {
7171
.await
7272
.context("Failed to create P2P node")?,
7373
);
74+
node.start().await.context("Failed to start P2P node")?;
7475

7576
// Get actual listen addresses after node creation
7677
let actual_addrs = node.listen_addrs().await;

src/messaging/service.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ impl MessagingService {
293293
}
294294

295295
let node = crate::network::P2PNode::new(node_config).await?;
296+
node.start().await?;
296297
Arc::new(node)
297298
};
298299
let transport = Arc::new(MessageTransport::new(network, dht_client.clone()).await?);

src/network.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,17 +1037,7 @@ impl P2PNode {
10371037
entangled_id: None,
10381038
binary_hash,
10391039
};
1040-
info!("Created P2P node with peer ID: {}", node.peer_id);
1041-
1042-
// Start the network listeners to populate listen addresses
1043-
node.start_network_listeners().await?;
1044-
1045-
// Update the connection monitor with actual peers reference
1046-
node.start_connection_monitor().await;
1047-
1048-
// Start message receiving system so messages work immediately after node creation
1049-
// This is critical for basic P2P messaging to work
1050-
node.start_message_receiving_system().await?;
1040+
info!("Created P2P node with peer ID: {} (call start() to begin networking)", node.peer_id);
10511041

10521042
Ok(node)
10531043
}
@@ -1159,12 +1149,13 @@ impl P2PNode {
11591149
// Start listening on configured addresses using transport layer
11601150
self.start_network_listeners().await?;
11611151

1152+
// Update the connection monitor with actual peers reference
1153+
self.start_connection_monitor().await;
1154+
11621155
// Log current listen addresses
11631156
let listen_addrs = self.listen_addrs.read().await;
11641157
info!("P2P node started on addresses: {:?}", *listen_addrs);
11651158

1166-
// MCP removed
1167-
11681159
// Start message receiving system
11691160
self.start_message_receiving_system().await?;
11701161

tests/connection_lifecycle_integration_test.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ async fn test_connection_lifecycle_with_keepalive() {
6666
};
6767

6868
let node1 = P2PNode::new(config1).await.expect("Failed to create node1");
69+
node1.start().await.expect("Failed to start node1");
6970
let node2 = P2PNode::new(config2).await.expect("Failed to create node2");
71+
node2.start().await.expect("Failed to start node2");
7072

7173
// Get their addresses
7274
let addrs1 = node1.listen_addrs().await;
@@ -182,7 +184,9 @@ async fn test_send_message_validates_connection_state() {
182184
};
183185

184186
let node1 = P2PNode::new(config1).await.expect("Failed to create node1");
187+
node1.start().await.expect("Failed to start node1");
185188
let node2 = P2PNode::new(config2).await.expect("Failed to create node2");
189+
node2.start().await.expect("Failed to start node2");
186190

187191
// Get addresses and connect
188192
let addrs2 = node2.listen_addrs().await;
@@ -265,7 +269,9 @@ async fn test_multiple_message_exchanges() {
265269
};
266270

267271
let node1 = P2PNode::new(config1).await.expect("Failed to create node1");
272+
node1.start().await.expect("Failed to start node1");
268273
let node2 = P2PNode::new(config2).await.expect("Failed to create node2");
274+
node2.start().await.expect("Failed to start node2");
269275

270276
// Connect nodes
271277
let addrs2 = node2.listen_addrs().await;

tests/connection_lifecycle_proof_test.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ async fn test_connection_lifecycle_infrastructure_exists() {
3737
};
3838

3939
let node = P2PNode::new(config).await.expect("Failed to create node");
40+
node.start().await.expect("Failed to start node");
4041

4142
info!("Node created successfully");
4243

@@ -112,6 +113,7 @@ async fn test_keepalive_task_initialized() {
112113
};
113114

114115
let _node = P2PNode::new(config).await.expect("Failed to create node");
116+
_node.start().await.expect("Failed to start node");
115117

116118
// The keepalive task is spawned in P2PNode::new() and runs in the background
117119
// It sends keepalive messages every 15 seconds to prevent the 30-second ant-quic timeout

tests/end_to_end_scenarios_test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ impl TestUser {
4646

4747
let peer_id = format!("test_user_{}", username);
4848
let node = P2PNode::new(config).await?;
49+
node.start().await?;
4950

5051
Ok(Self {
5152
node: Arc::new(node),
@@ -55,7 +56,7 @@ impl TestUser {
5556
}
5657

5758
async fn start(&self) -> Result<()> {
58-
// TODO: Implement when node.start() API is available
59+
// Node is already started after P2PNode::new() + start() in TestUser::new()
5960
sleep(Duration::from_millis(100)).await;
6061
Ok(())
6162
}

0 commit comments

Comments
 (0)