ts-leaky-bucket
v1.1.1
Published
Port of [leaky-bucket](https://github.com/linaGirl/leaky-bucket) to Typescript. Original package was using experimental modules which required a runtime flag and also didn't have nice Typescript types.
Downloads
31
Readme
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 thismaybeThrottle
append
- 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 givenmillis
pauseByCost(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 work
Await 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
=>awaitEmpty
to capture that a call to this waits until the queue emptiesthrottle
=>maybeThrottle
to capture that it may return immediately if there is capacity or wait if notinterval
=>intervalMillis
clarify unit of timetimeout
=>additionalTimeoutMillis
clarify unit of time and also make clear this is in addition tointervalMillis
requestRate
=>requestRateInSecs
clarify 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
,timeout
at runtime which I didn't want to encourage additionalTimeoutMillis
is added tointervalMillis
instead of treated as a independent variablepause(millis: number)
uses milliseconds instead of seconds to be consistent- uses
get
ters instead ofgetXXX
for reading options back out