fix: improve connection manager error handling + edge cases (#1450)

* increase TTL on discovery classes

* refactor dialPeer to handle edge cases

* address comment
This commit is contained in:
Danish Arora 2023-08-02 13:49:48 +05:30 committed by GitHub
parent 0b8936f1f1
commit 785df528fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 54 deletions

View File

@ -174,51 +174,67 @@ export class ConnectionManager
private async dialPeer(peerId: PeerId): Promise<void> {
this.currentActiveDialCount += 1;
let dialAttempt = 0;
while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
while (dialAttempt < this.options.maxDialAttemptsForPeer) {
try {
log(`Dialing peer ${peerId.toString()}`);
log(`Dialing peer ${peerId.toString()} on attempt ${dialAttempt + 1}`);
await this.libp2p.dial(peerId);
const tags = await this.getTagNamesForPeer(peerId);
// add tag to connection describing discovery mechanism
// don't add duplicate tags
this.libp2p
.getConnections(peerId)
.forEach(
(conn) => (conn.tags = Array.from(new Set([...conn.tags, ...tags])))
);
this.libp2p.getConnections(peerId).forEach((conn) => {
conn.tags = Array.from(new Set([...conn.tags, ...tags]));
});
this.dialAttemptsForPeer.delete(peerId.toString());
return;
} catch (e) {
const error = e as AggregateError;
this.dialErrorsForPeer.set(peerId.toString(), error);
// Dialing succeeded, break the loop
break;
} catch (error) {
if (error instanceof AggregateError) {
// Handle AggregateError
log(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
dialAttempt = this.dialAttemptsForPeer.get(peerId.toString()) ?? 1;
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt + 1);
if (dialAttempt <= this.options.maxDialAttemptsForPeer) {
log(`Reattempting dial (${dialAttempt})`);
}
}
}
try {
} else {
// Handle generic error
log(
`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${JSON.stringify(
this.dialErrorsForPeer.get(peerId.toString()).errors[0]
)}
`Error dialing peer ${peerId.toString()} - ${
(error as any).message
}`
);
this.dialErrorsForPeer.delete(peerId.toString());
return await this.libp2p.peerStore.delete(peerId);
} catch (error) {
throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
} finally {
this.currentActiveDialCount -= 1;
}
this.dialErrorsForPeer.set(peerId.toString(), error);
dialAttempt++;
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt);
}
}
// Always decrease the active dial count and process the dial queue
this.currentActiveDialCount--;
this.processDialQueue();
// If max dial attempts reached and dialing failed, delete the peer
if (dialAttempt === this.options.maxDialAttemptsForPeer) {
try {
const error = this.dialErrorsForPeer.get(peerId.toString());
let errorMessage;
if (error instanceof AggregateError) {
errorMessage = JSON.stringify(error.errors[0]);
} else {
errorMessage = error.message;
}
log(
`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${errorMessage}`
);
this.dialErrorsForPeer.delete(peerId.toString());
await this.libp2p.peerStore.delete(peerId);
} catch (error) {
throw new Error(
`Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`
);
}
}
}
@ -302,25 +318,16 @@ export class ConnectionManager
Tags.BOOTSTRAP
);
if (isBootstrap) {
this.dispatchEvent(
new CustomEvent<PeerId>(
EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP,
isBootstrap
? EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP
: EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
{
detail: peerId,
}
)
);
} else {
this.dispatchEvent(
new CustomEvent<PeerId>(
EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
{
detail: peerId,
}
)
);
}
try {
await this.attemptDial(peerId);

View File

@ -22,7 +22,7 @@ const enrTree = {
const DEFAULT_BOOTSTRAP_TAG_NAME = "bootstrap";
const DEFAULT_BOOTSTRAP_TAG_VALUE = 50;
const DEFAULT_BOOTSTRAP_TAG_TTL = 120000;
const DEFAULT_BOOTSTRAP_TAG_TTL = 100_000_000;
export interface DnsDiscoveryComponents {
peerStore: PeerStore;

View File

@ -47,7 +47,7 @@ export interface Options {
export const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
const DEFAULT_PEER_EXCHANGE_TAG_TTL = 120000;
const DEFAULT_PEER_EXCHANGE_TAG_TTL = 100_000_000;
export class PeerExchangeDiscovery
extends EventEmitter<PeerDiscoveryEvents>