
Porro is a simple and fast implementation of the leaky bucket algorithm.
Naming things is hard
During a scene in Cloudy with a Chance of Meatballs 2, the protagonists are moving with a boat. At some point, a wild tribe of living leeks attacks the boat, and the scientist shouts: "There's a leak in the boat!". Porro means leek in Italian. Leaky bucket algorithm -> Leak -> Leek -> Porro.
Features
- No dependencies: small footprint.
- No timers: unlike some other implementations, Porro doesn't use any timer.
- ES modules support: native Node.js
import
/export
. - CommonJS support: common runtimes are still supported.
- ES6: code just uses ES6 features.
- TypeScript: this package includes its own TypeScript declarations.
Install
Open your favourite shell and run:
npm install porro
API
new Porro(options)
Porro's constructor
.
options
<Object>
- bucketSize
<Number>
The size (number of tokens) of the bucket. - interval
<Number>
Time interval in milliseconds to refill the bucket. - tokensPerInterval
<Number>
Number of refilled tokens after the specified interval.
- Returns:
<Porro>
Porro::tokens
Returns (getter) the current number of tokens inside the bucket.
Porro::request([quantity])
Returns the amount of time that the pending request needs to wait before executing.
[quantity]
<Number>
Number (positive integer) of tokens to burn for the current request. Defaults to 1
.- Returns:
<Number>
Porro::throttle([quantity])
Returns a Promise
that will resolve when It's appropriate to execute the pending request.
[quantity]
<Number>
Number (positive integer) of tokens to burn for the current request. Defaults to 1
.- Returns:
<Promise>
Resolves with the waited milliseconds.
Porro::reset()
Resets the bucket to its original status.
Example
import { Porro } from 'porro'
const bucket = new Porro({
bucketSize: 5,
interval: 1000,
tokensPerInterval: 2
})
async function run () {
const items = new Array(10).fill(null)
log('script is starting')
await Promise.all(items.map(doSomething))
}
async function doSomething (value, index) {
const ms = bucket.request()
if (ms > 0) {
log(`request #${index} will wait ${ms}ms`)
await sleep(ms)
}
log(`run request #${index}`)
}
function log (message) {
console.log(`[${new Date().toISOString()}]`, message, `(bucket has now ${bucket.tokens} tokens)`)
}
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
run()