ts-leaky-bucket v1.1.1
TS Leaky Bucket
Port of leaky-bucket to Typescript. Original package was using experimental modules which required a runtime flag and also didn't have nice Typescript types.
Overview
Implementation of a leaky bucket algorithm to support throttling / rate limiting. Check out ts-request-rate-limiter if you are looking for a library to limit client requests (e.g. rate limiting requests to an API).
Install
npm i ts-leaky-bucket
Usage
Create a LeakyBucket
Constructor Options
capacity- unit of capacity of a bucketintervalMillis- time to fully drain the buckettimeoutMillis- time to queue additional items over capacity
import { LeakyBucket, LeakyBucketOptions } from "ts-leaky-bucket";
const options: LeakyBucketOptions = {
capacity: 120,
intervalMillis: 60_000,
timeoutMillis: 300_000,
}
// constructor takes `LeakyBucketOptions`
const bucket = new LeakyBucket(options);
// OR just use constructor directly
// constructor with options
const bucket = new LeakyBucket({
capacity: 120,
intervalMillis: 60_000,
timeoutMillis: 300_000,
});Throttling
Way to add things to a bucket and then wait for the bucket to leak them.
maybeThrottle(cost: number = 1, append: boolean = true, isPause: boolean = false): Promise<void>
cost- how much unit capacity to take for thismaybeThrottleappend- add to back of queue or beginningisPause- used to denote an item being a pause request
import { LeakyBucket, LeakyBucketOptions } from "ts-leaky-bucket";
const bucket = new LeakyBucket({
capacity: 120,
intervalMillis: 60_000,
timeoutMillis: 300_000,
});
async myBizLogicToThrottle(): void {
// wait for bucket to say we are ready
await maybeThrottle(20); // 20 units of capacity
// now do work
myBizLogic();
}Pausing
Two ways to pause the bucket from leaking:
pause(millis = 1000)- pause the bucket from leaking for givenmillispauseByCost(cost: number)- pauses the bucket from leaking for a given forcost
// create bucket
...
// do throttled work
...
// pause leaking for a second
await bucket.pause();
// pause for 100 units of cost
await bucket.pauseForCost(100);
// do more thottled workAwait Empty
If you want to wait for all items to leak out of a bucket you can use awaitEmpty.
// create bucket
...
// do throttled work
...
// wait for bucket to empty
await bucket.awaitEmpty();Other Methods
pay(cost: number)- post-hoc leak after a throttle to pay down additional unit coststopTimerAndClearQueue- clear the timer and queue
Development Commands
npm i- install depsnpm run test- run testsnpm run publish- publish
Changes
I've changed the code a bit from the original:
- Naming changes
isEmpty=>awaitEmptyto capture that a call to this waits until the queue emptiesthrottle=>maybeThrottleto capture that it may return immediately if there is capacity or wait if notinterval=>intervalMillisclarify unit of timetimeout=>additionalTimeoutMillisclarify unit of time and also make clear this is in addition tointervalMillisrequestRate=>requestRateInSecsclarify unit of time
- API Changes
- Uses milliseconds as the time unit instead of a mix between seconds and milliseconds
- Does not allow post creation options changing; Original allows updating
capacity,interval,timeoutat runtime which I didn't want to encourage additionalTimeoutMillisis added tointervalMillisinstead of treated as a independent variablepause(millis: number)uses milliseconds instead of seconds to be consistent- uses
getters instead ofgetXXXfor reading options back out