prom-utils
Version:
Promise utilities: rate limiting, queueing/batching, defer, etc.
129 lines (116 loc) • 3.65 kB
text/typescript
export type LastFlush =
| { timeout: number }
| { batchSize: number }
| { batchBytes: number }
export interface QueueStats {
itemsPerSec: number
bytesPerSec: number
}
export type QueueResult<A, B> = {
/** Call `fn` with the items in the queue. */
flush(): Promise<void>
/** Add an item to the queue. When a queue condition is met `flush` will be called. */
enqueue(item: A): Promise<void>
/** The last result returned from calling `fn`. */
lastResult?: Awaited<B>
/**
* The cause for the last automatic queue flush. Will be one of the
* following: timeout, batchSize, or batchBytes.
*/
lastFlush?: LastFlush
/** Get the current throughput rates. */
getStats(): QueueStats
/** Length of the queue. */
get length(): number
}
export type QueueResultParallel<A, B> = {
/** Call `fn` with the items in the queue. */
flush(): void
/** Add an item to the queue. When a queue condition is met `flush` will be called. */
enqueue(item: A): void
/** Array of accumulated results for all callback calls. */
results: B[]
/**
* The cause for the last automatic queue flush. Will be one of the
* following: batchSize or batchBytes.
*/
lastFlush?: LastFlush
/** Length of the queue. */
get length(): number
}
export interface RateLimitOptions {
/**
* Maximum throughput allowed (items/period). Defaults to items/sec.
*/
maxItemsPerPeriod?: number
}
export interface AddOptions {
/**
* Bypass async waiting. This is useful when the item being added is the
* last item and you are limiting throughput.
*/
bypass?: boolean
}
export interface QueueOptionsParallel {
/**
* Wait for the batch to reach this number of elements before flushing the queue.
* Defaults to 500
*/
batchSize?: number
/** Wait for the batch to reach this size in bytes before flushing the queue. */
batchBytes?: number
}
export interface QueueOptions extends QueueOptionsParallel {
/** Wait this long in ms before flushing the queue. */
timeout?: number
/** Maximum throughput allowed (item/sec). */
maxItemsPerSec?: number
/** Maximum throughput allowed (bytes/sec). */
maxBytesPerSec?: number
}
export interface Deferred {
/** Resolve the promise. */
done: () => void
/** Resolves when `done` is called. */
promise: Promise<void>
}
export interface WaitOptions {
/** Wait this long in ms before rejecting. Defaults to 5000 ms. */
timeout?: number
/** Check the predicate with this frequency. Defaults to 50 ms. */
checkFrequency?: number
}
export type SlidingWindow = { timestamp: number; numUnits: number }[]
export type GetTimeframe = (
slidingWindow: SlidingWindow,
options: Required<ThroughputLimiterOptions>
) => number
export interface ThroughputLimiterOptions {
/**
* The period of time in ms to track the rate. Set to 60_000 for 1 minute.
* Defaults to 1000, which is units/sec.
*/
period?: number
/**
* The minimum number of throttle invocations prior to checking the rate.
* Use this to allow for short bursts without throttling.
* Should be 1 or more. Defaults to 1.
*/
minWindowLength?: number
/**
* The maximum number of throttle invocations to hold in memory.
* Should be 1 or more. Defaults to 3.
*/
maxWindowLength?: number
/**
* Expire throttle invocations after this many ms.
* Defaults to Infinity.
*/
expireAfter?: number
/**
* The timeframe to use for calculating the rate. There are two functions
* provided: `getTimeframeUsingElapsed` and `getTimeframeUsingPeriod`.
* The default is `getTimeframeUsingElapsed`.
*/
getTimeframe?: GetTimeframe
}