mirror of
https://github.com/hcengineering/platform.git
synced 2025-02-06 11:01:49 +00:00
40 lines
1.0 KiB
TypeScript
40 lines
1.0 KiB
TypeScript
|
/**
|
||
|
* @public
|
||
|
*/
|
||
|
|
||
|
export class RateLimitter {
|
||
|
idCounter: number = 0
|
||
|
processingQueue = new Map<string, Promise<void>>()
|
||
|
|
||
|
queue: (() => Promise<void>)[] = []
|
||
|
|
||
|
constructor (readonly config: () => { rate: number }) {}
|
||
|
|
||
|
async exec<T, B extends Record<string, any> = {}>(op: (args?: B) => Promise<T>, args?: B): Promise<T> {
|
||
|
const processingId = `${this.idCounter++}`
|
||
|
|
||
|
if (this.processingQueue.size > this.config().rate) {
|
||
|
await Promise.race(this.processingQueue.values())
|
||
|
}
|
||
|
try {
|
||
|
const p = op(args)
|
||
|
this.processingQueue.set(processingId, p as Promise<void>)
|
||
|
return await p
|
||
|
} finally {
|
||
|
this.processingQueue.delete(processingId)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async add<T, B extends Record<string, any> = {}>(op: (args?: B) => Promise<T>, args?: B): Promise<void> {
|
||
|
if (this.processingQueue.size < this.config().rate) {
|
||
|
void this.exec(op, args)
|
||
|
} else {
|
||
|
await this.exec(op, args)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async waitProcessing (): Promise<void> {
|
||
|
await await Promise.race(this.processingQueue.values())
|
||
|
}
|
||
|
}
|