feat: use reliability manager in lightpush only if retry passed, imrpvoe implementation

This commit is contained in:
Sasha 2024-10-09 01:38:38 +02:00
parent 75fcca4cd9
commit 0245f060f5
No known key found for this signature in database
3 changed files with 38 additions and 45 deletions

View File

@ -104,10 +104,10 @@ class LightPush extends BaseProtocolSDK implements ILightPush {
connectedPeer.id.equals(failure.peerId)
);
if (connectedPeer) {
if (connectedPeer && _options?.autoRetry) {
void this.reliabilityMonitor.attemptRetriesOrRenew(
connectedPeer.id,
() => this.protocol.send(encoder, message, connectedPeer)
connectedPeer,
(peer) => this.protocol.send(encoder, message, peer)
);
}
}

View File

@ -1,4 +1,4 @@
import type { Peer, PeerId } from "@libp2p/interface";
import type { Connection, Peer, PeerId } from "@libp2p/interface";
import {
ContentTopic,
CoreProtocolResult,
@ -42,10 +42,12 @@ export class ReliabilityMonitorManager {
}
public static createSenderMonitor(
getConnection: () => Connection[],
renewPeer: (peerId: PeerId) => Promise<Peer>
): SenderReliabilityMonitor {
if (!ReliabilityMonitorManager.senderMonitor) {
ReliabilityMonitorManager.senderMonitor = new SenderReliabilityMonitor(
getConnection,
renewPeer
);
}

View File

@ -1,56 +1,47 @@
import type { Peer, PeerId } from "@libp2p/interface";
import { CoreProtocolResult, PeerIdStr } from "@waku/interfaces";
import type { Connection, Peer, PeerId } from "@libp2p/interface";
import { CoreProtocolResult } from "@waku/interfaces";
import { Logger } from "@waku/utils";
const log = new Logger("sdk:sender:reliability_monitor");
const DEFAULT_MAX_ATTEMPTS_BEFORE_RENEWAL = 3;
const DEFAULT_MAX_ATTEMPTS = 3;
export class SenderReliabilityMonitor {
private attempts: Map<PeerIdStr, number> = new Map();
private readonly maxAttemptsBeforeRenewal =
DEFAULT_MAX_ATTEMPTS_BEFORE_RENEWAL;
public constructor(private renewPeer: (peerId: PeerId) => Promise<Peer>) {}
public constructor(
private getConnections: () => Connection[],
private renewPeer: (peerId: PeerId) => Promise<Peer>
) {}
public async attemptRetriesOrRenew(
peerId: PeerId,
protocolSend: () => Promise<CoreProtocolResult>
peerToUse: Peer,
protocolSend: (p: Peer) => Promise<CoreProtocolResult>
): Promise<void> {
const peerIdStr = peerId.toString();
const currentAttempts = this.attempts.get(peerIdStr) || 0;
this.attempts.set(peerIdStr, currentAttempts + 1);
if (currentAttempts + 1 < this.maxAttemptsBeforeRenewal) {
try {
const result = await protocolSend();
if (result.success) {
log.info(`Successfully sent message after retry to ${peerIdStr}`);
this.attempts.delete(peerIdStr);
} else {
log.error(
`Failed to send message after retry to ${peerIdStr}: ${result.failure}`
);
await this.attemptRetriesOrRenew(peerId, protocolSend);
let forceRenew = false;
for (let i = 0; i < DEFAULT_MAX_ATTEMPTS; i++) {
const connections = this.getConnections();
if (
forceRenew ||
!connections.find((c) => c.remotePeer.equals(peerToUse.id))
) {
try {
peerToUse = await this.renewPeer(peerToUse.id);
forceRenew = false;
} catch (e) {
log.error(`Failed to renew peer ${peerToUse.id.toString()}: ${e}`);
return;
}
} catch (error) {
log.error(
`Failed to send message after retry to ${peerIdStr}: ${error}`
);
await this.attemptRetriesOrRenew(peerId, protocolSend);
}
} else {
try {
const newPeer = await this.renewPeer(peerId);
log.info(
`Renewed peer ${peerId.toString()} to ${newPeer.id.toString()}`
);
this.attempts.delete(peerIdStr);
this.attempts.set(newPeer.id.toString(), 0);
await protocolSend();
} catch (error) {
log.error(`Failed to renew peer ${peerId.toString()}: ${error}`);
try {
const result = await protocolSend(peerToUse);
if (result.success) {
return;
}
forceRenew = true;
} catch (_e) {
continue;
}
}
}