Skip to content

Commit 4577292

Browse files
authored
chore: Removed pruning of the duplicate connections (#16461)
Removes pruning of "duplicate" peer connections. Libp2p manages this, but more importantly, it's perfectly fine to have multiple connections per peer. ([source](https://discuss.libp2p.io/t/random-walk-peer-discovery-adds-connections-to-same-peer/584)) Finally, choosing the most recent ones to remove seems somewhat arbitrary (i.e., why not prune the oldest). With this change, the preferred gossip test hasn't flaked for me using `grind` at all.
2 parents 8fd3ab3 + 4b87cd8 commit 4577292

File tree

2 files changed

+1
-72
lines changed

2 files changed

+1
-72
lines changed

yarn-project/p2p/src/services/peer-manager/peer_manager.test.ts

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -415,40 +415,6 @@ describe('PeerManager', () => {
415415
expect(mockLibP2PNode.hangUp).toHaveBeenCalledTimes(2);
416416
});
417417

418-
it('should disconnect from duplicate peers during heartbeat', async () => {
419-
// Create a peer that will have duplicate connections
420-
const peerId = await createSecp256k1PeerId();
421-
422-
// Create mock connections with different timestamps to simulate connections opened at different times
423-
const oldestConnection = {
424-
remotePeer: peerId,
425-
timeline: { open: 1000 },
426-
close: jest.fn(),
427-
};
428-
const duplicateConnection1 = {
429-
remotePeer: peerId,
430-
timeline: { open: 2000 },
431-
close: jest.fn(),
432-
};
433-
const duplicateConnection2 = {
434-
remotePeer: peerId,
435-
timeline: { open: 3000 },
436-
close: jest.fn(),
437-
};
438-
mockLibP2PNode.getConnections.mockReturnValue([duplicateConnection1, oldestConnection, duplicateConnection2]);
439-
440-
// Trigger heartbeat which should call pruneDuplicatePeers
441-
await peerManager.heartbeat();
442-
443-
await sleep(100);
444-
445-
// Verify that the duplicate connections were closed
446-
expect(duplicateConnection1.close).toHaveBeenCalled();
447-
expect(duplicateConnection2.close).toHaveBeenCalled();
448-
// Verify that the oldest connection was not closed
449-
expect(oldestConnection.close).not.toHaveBeenCalled();
450-
});
451-
452418
it('should properly clean up peers on stop', async () => {
453419
mockLibP2PNode.getPeers.mockReturnValue([await createSecp256k1PeerId(), await createSecp256k1PeerId()]);
454420

@@ -692,9 +658,6 @@ describe('PeerManager', () => {
692658
// This ensures prioritizePeers gets the correct connections
693659
jest.spyOn(peerManager as any, 'pruneUnhealthyPeers').mockImplementation(connections => connections);
694660

695-
// Mock the pruneDuplicatePeers method to return the connections unchanged
696-
jest.spyOn(peerManager as any, 'pruneDuplicatePeers').mockImplementation(connections => connections);
697-
698661
// Trigger heartbeat which should call prioritizePeers
699662
await peerManager.heartbeat();
700663

yarn-project/p2p/src/services/peer-manager/peer_manager.ts

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,7 @@ export class PeerManager implements PeerManagerInterface {
499499
private discover() {
500500
const connections = this.libP2PNode.getConnections();
501501

502-
const healthyConnections = this.prioritizePeers(
503-
this.pruneUnhealthyPeers(this.getNonProtectedPeers(this.pruneDuplicatePeers(connections))),
504-
);
502+
const healthyConnections = this.prioritizePeers(this.pruneUnhealthyPeers(this.getNonProtectedPeers(connections)));
505503

506504
// Calculate how many connections we're looking to make
507505
const protectedPeerCount = this.getProtectedPeerCount();
@@ -623,38 +621,6 @@ export class PeerManager implements PeerManagerInterface {
623621
}
624622
}
625623

626-
/**
627-
* If multiple connections to the same peer are found, the oldest connection is kept and the duplicates are pruned.
628-
*
629-
* This is necessary to resolve a race condition where multiple connections to the same peer are established if
630-
* they are discovered at the same time.
631-
*
632-
* @param connections - The list of connections to prune duplicate peers from.
633-
* @returns The pruned list of connections.
634-
*/
635-
private pruneDuplicatePeers(connections: Connection[]): Connection[] {
636-
const peerConnections = new Map<string, Connection>();
637-
638-
for (const conn of connections) {
639-
const peerId = conn.remotePeer.toString();
640-
const existingConnection = peerConnections.get(peerId);
641-
if (!existingConnection) {
642-
peerConnections.set(peerId, conn);
643-
} else {
644-
// Keep the oldest connection for each peer
645-
this.logger.debug(`Found duplicate connection to peer ${peerId}, keeping oldest connection`);
646-
if (conn.timeline.open < existingConnection.timeline.open) {
647-
peerConnections.set(peerId, conn);
648-
void existingConnection.close();
649-
} else {
650-
void conn.close();
651-
}
652-
}
653-
}
654-
655-
return [...peerConnections.values()];
656-
}
657-
658624
private async goodbyeAndDisconnectPeer(peer: PeerId, reason: GoodByeReason) {
659625
this.logger.debug(`Disconnecting peer ${peer.toString()} with reason ${prettyGoodbyeReason(reason)}`);
660626

0 commit comments

Comments
 (0)