-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(lightpush): introduce ReliabilityMonitor and allow
send
retries (
#2130) * chore: restructure reliabiltiy monitors * feat: setup sender monitor * chore: update tests * chore: minor fixes * chore: comment for doc
- Loading branch information
1 parent
7ad1d32
commit 7a6247c
Showing
9 changed files
with
172 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import type { Peer, PeerId } from "@libp2p/interface"; | ||
import { | ||
ContentTopic, | ||
CoreProtocolResult, | ||
PubsubTopic | ||
} from "@waku/interfaces"; | ||
|
||
import { ReceiverReliabilityMonitor } from "./receiver.js"; | ||
import { SenderReliabilityMonitor } from "./sender.js"; | ||
|
||
export class ReliabilityMonitorManager { | ||
private static receiverMonitors: Map< | ||
PubsubTopic, | ||
ReceiverReliabilityMonitor | ||
> = new Map(); | ||
private static senderMonitor: SenderReliabilityMonitor | undefined; | ||
|
||
public static createReceiverMonitor( | ||
pubsubTopic: PubsubTopic, | ||
getPeers: () => Peer[], | ||
renewPeer: (peerId: PeerId) => Promise<Peer>, | ||
getContentTopics: () => ContentTopic[], | ||
protocolSubscribe: ( | ||
pubsubTopic: PubsubTopic, | ||
peer: Peer, | ||
contentTopics: ContentTopic[] | ||
) => Promise<CoreProtocolResult> | ||
): ReceiverReliabilityMonitor { | ||
if (ReliabilityMonitorManager.receiverMonitors.has(pubsubTopic)) { | ||
return ReliabilityMonitorManager.receiverMonitors.get(pubsubTopic)!; | ||
} | ||
|
||
const monitor = new ReceiverReliabilityMonitor( | ||
pubsubTopic, | ||
getPeers, | ||
renewPeer, | ||
getContentTopics, | ||
protocolSubscribe | ||
); | ||
ReliabilityMonitorManager.receiverMonitors.set(pubsubTopic, monitor); | ||
return monitor; | ||
} | ||
|
||
public static createSenderMonitor( | ||
renewPeer: (peerId: PeerId) => Promise<Peer> | ||
): SenderReliabilityMonitor { | ||
if (!ReliabilityMonitorManager.senderMonitor) { | ||
ReliabilityMonitorManager.senderMonitor = new SenderReliabilityMonitor( | ||
renewPeer | ||
); | ||
} | ||
return ReliabilityMonitorManager.senderMonitor; | ||
} | ||
|
||
private constructor() {} | ||
|
||
public static stop(pubsubTopic: PubsubTopic): void { | ||
this.receiverMonitors.delete(pubsubTopic); | ||
this.senderMonitor = undefined; | ||
} | ||
|
||
public static stopAll(): void { | ||
for (const [pubsubTopic, monitor] of this.receiverMonitors) { | ||
monitor.setMaxMissedMessagesThreshold(undefined); | ||
monitor.setMaxPingFailures(undefined); | ||
this.receiverMonitors.delete(pubsubTopic); | ||
this.senderMonitor = undefined; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import type { Peer, PeerId } from "@libp2p/interface"; | ||
import { CoreProtocolResult, PeerIdStr } from "@waku/interfaces"; | ||
import { Logger } from "@waku/utils"; | ||
|
||
const log = new Logger("sdk:sender:reliability_monitor"); | ||
|
||
const DEFAULT_MAX_ATTEMPTS_BEFORE_RENEWAL = 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 async attemptRetriesOrRenew( | ||
peerId: PeerId, | ||
protocolSend: () => 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); | ||
} | ||
} 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}`); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters