Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 5x 5x 61x 61x 61x 378x 378x 378x 378x 378x 59x 319x 260x 319x 319x 59x 58x 58x 58x 58x 378x 378x 58x 58x 58x 58x 117x 117x 117x 117x 117x 117x 117x 61x | type Callback<T> = () => PromiseLike<T> interface Event<T> { getPromise?: Callback<T> resolve: (result: T | PromiseLike<T>) => void reject: (...args: unknown[]) => void number: number } export class LimiterError extends Error {} export function createLimiter<T = void>( interval: number, noLimitCount: number ) { let currentNumber = 0 let lastCompletedNumber = 0 let events: number[] = [] let timeout: number | undefined let lastEvent: Event<T> | undefined function limited(getPromise?: Callback<T>): PromiseLike<T> { return new Promise<T>((resolve, reject) => { currentNumber += 1 const event: Event<T> = { getPromise, resolve, reject, number: currentNumber, } removeOldEvents() if (events.length < noLimitCount) { execute(event) } else { if (lastEvent !== undefined) { lastEvent.reject(new LimiterError("rate limit exceeded")) } lastEvent = event if (timeout === undefined) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore timeout = setTimeout(() => { timeoutAction() }, interval) } } }) } function stop() { if (timeout !== undefined) { clearTimeout(timeout) } timeout = undefined } function removeOldEvents() { const t = new Date().getTime() - interval * noLimitCount events = events.filter(v => v >= t) } function timeoutAction() { if (lastEvent !== undefined) { execute(lastEvent) lastEvent = undefined stop() } } async function execute(event: Event<T>) { events.push(new Date().getTime()) if (event.getPromise !== undefined) { try { const result = await event.getPromise() if (event.number > lastCompletedNumber) { lastCompletedNumber = event.number event.resolve(result) } else E{ event.reject(new LimiterError("Got newer event")) } } catch (e) { event.reject(e) } } else E{ // @ts-expect-error no result given event.resolve() } } return { limited, } } |