UNPKG

@waku/sdk

Version:

A unified SDK for easy creation and management of js-waku nodes.

113 lines 3.6 kB
import { Protocols } from "@waku/interfaces"; import { Logger } from "@waku/utils"; import { shouldPeerBeChanged, timeout } from "./utils.js"; const MAX_CONCURRENT_TASKS = 5; const TASK_TIMEOUT_MS = 10_000; const log = new Logger("sdk:retry-manager"); export class RetryManager { intervalID = null; retryIntervalMs; inProgress = 0; queue = []; peerManager; constructor(config) { this.peerManager = config.peerManager; this.retryIntervalMs = config.retryIntervalMs || 1000; } start() { this.intervalID = setInterval(() => { this.processQueue(); }, this.retryIntervalMs); } stop() { if (this.intervalID) { clearInterval(this.intervalID); this.intervalID = null; } } push(callback, maxAttempts, routingInfo) { this.queue.push({ maxAttempts, callback, routingInfo }); } processQueue() { if (this.queue.length === 0) { return; } while (this.queue.length && this.inProgress < MAX_CONCURRENT_TASKS) { const task = this.queue.shift(); if (task) { this.scheduleTask(task); } } } scheduleTask(task) { const delayedTask = async () => { return this.taskExecutor(task); }; // schedule execution ASAP // need to use setTimeout to avoid blocking main execution setTimeout(delayedTask, 100); } async taskExecutor(task) { if (task.maxAttempts <= 0) { log.warn("scheduleTask: max attempts has reached, removing from queue"); return; } const peerId = (await this.peerManager.getPeers({ protocol: Protocols.LightPush, pubsubTopic: task.routingInfo.pubsubTopic }))[0]; if (!peerId) { log.warn("scheduleTask: no peers, putting back to queue"); this.queue.push({ ...task, maxAttempts: task.maxAttempts - 1 }); return; } try { this.inProgress += 1; const response = await Promise.race([ timeout(TASK_TIMEOUT_MS), task.callback(peerId) ]); if (response?.failure) { throw Error(response.failure.error); } log.info("scheduleTask: executed successfully"); if (task.maxAttempts === 0) { log.warn("scheduleTask: discarded a task due to limit of max attempts"); return; } this.queue.push({ ...task, maxAttempts: task.maxAttempts - 1 }); } catch (_err) { const error = _err; log.error("scheduleTask: task execution failed with error:", error); if (shouldPeerBeChanged(error.message)) { await this.peerManager.renewPeer(peerId, { protocol: Protocols.LightPush, pubsubTopic: task.routingInfo.pubsubTopic }); } if (task.maxAttempts === 0) { log.warn("scheduleTask: discarded a task due to limit of max attempts"); return; } this.queue.push({ ...task, maxAttempts: task.maxAttempts - 1 }); } finally { this.inProgress -= 1; } } } //# sourceMappingURL=retry_manager.js.map