UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

97 lines (75 loc) 2.48 kB
import * as Collections from '../common/Collections'; import { createLogger } from '../common/logger'; import { OngoingRequestsNotification } from './messagetypes/OngoingRequests'; const logger = createLogger('OngoingRequests'); export type ActiveOngoingRequest = { requestId: string, remotePeerId: string, storageId: string } export class OngoingRequestsNotifier { private readonly _activeOngoingRequests = new Map<string, ActiveOngoingRequest>(); private _timer?: ReturnType<typeof setInterval>; public constructor( public readonly timeoutInMs: number, private readonly _sender: (notification: OngoingRequestsNotification) => void, ) { } public get activeOngoingRequests(): ReadonlyMap<string, ActiveOngoingRequest> { return this._activeOngoingRequests; } public has(requestId: string): boolean { if (!requestId) return false; return this._activeOngoingRequests.has(requestId); } public add(activeOngoingRequest: ActiveOngoingRequest): void { if (this._activeOngoingRequests.has(activeOngoingRequest.requestId)) { return; } this._activeOngoingRequests.set(activeOngoingRequest.requestId, activeOngoingRequest); logger.trace('Added ongoing request %o', activeOngoingRequest); if (!this._timer) { this._startTimer(); } } public remove(requestId: string): boolean { if (!this._activeOngoingRequests.has(requestId)) { return false; } this._activeOngoingRequests.delete(requestId); logger.trace('Removed ongoing request %s', requestId); if (this._activeOngoingRequests.size < 1) { this._stopTimer(); } return true; } public clear() { this._activeOngoingRequests.clear(); this._stopTimer(); } private _startTimer(): void { if (this._timer) { return logger.warn('Attempted to start a timer twice'); } this._timer = setInterval(() => { if (this._activeOngoingRequests.size < 1) { return (this._timer = undefined); } const remotePeerActiveRequests = Collections.groupArrayBy([ ...this._activeOngoingRequests.values() ], (item) => item.remotePeerId); for (const [ remotePeerId, ongoingRequests ] of remotePeerActiveRequests) { const notification = new OngoingRequestsNotification( new Set(ongoingRequests.map((item) => item.requestId)), remotePeerId ); this._sender(notification); } }, this.timeoutInMs); } private _stopTimer(): void { if (!this._timer) { return; } clearInterval(this._timer); this._timer = undefined; } }