hamok
Version:
Lightweight Distributed Object Storage on RAFT consensus algorithm
97 lines (75 loc) • 2.48 kB
text/typescript
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;
}
}