NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #2706 most downloaded on npm
Distributed task scheduler and rate limiter
Last release 7 years ago
no release in 18 months
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
13 years old
79 releases · first in 2014
Fixes a minor and rare race condition in Clustering due to an inconsistent network. The only negative effects were an error message and an expired job
Fixes a few issues with the TypeScript type definitions.
One column per quarter.
Allow directly passing the redis/ioredis module. This fixes an issue for Clustering users that bundle their app, as seen in serverless environments. T
Fixed an issue when using Redis Cluster and a custom Redis client object. Thank you @marektihkan for the excellent bug report #129
light bundle, it would broadcast a lot of annoying but harmless exceptions on the error listener. Thank you @richtera for the excellent bug report #127The "failed" event listener typings did not allow returning undefined / null or Promise<undefined> / Promise<null> .
The "failed" event listener typings did not allow returning undefined/null or Promise<undefined>/Promise<null>.
Thank you @dobesv for your contribution!
Added the following events: received , queued , scheduled , executing and done .
received, queued, scheduled, executing and done.They map to Jobs Lifecycle transitions. These events are local to a limiter inside a Cluster, for performance reasons.
Thank you @lp-wodell for the feature suggestion! #124
Reduced the memory usage of queued jobs by 40%.
This massive gain is thanks to a refactor of the engine internals. The behavior of this module should be unchanged. If Bottleneck 2.18.1 behaves differently from 2.18.0 in your application, please open an issue.
catch would not trigger the Node.js "Unhandled Promise Rejection" warning.This has been fixed and Node now correctly alerts you, as this points to a bug in your application. async/await users: wrap your jobs into a try/catch at the place where the job is await'ed. Promise users: make sure your jobs have a .catch().
Added Increase Intervals . Similar to the Refresh Interval, it increases a limiter's reservoir on an interval. Instead of resetting the reservoir to a
Added Increase Intervals. Similar to the Refresh Interval, it increases a limiter's reservoir on an interval. Instead of resetting the reservoir to a specific value, it increments the reservoir by a certain value, up to an optional maximum value.
Thanks @TheGame2500 and @tomblanchard for suggesting this feature.
Optimized Clustering code for use cases where short lived clients are created at a high rate.
Optimized Clustering code for use cases where short lived clients are created at a high rate.
Bottleneck now ensures that jobs passed to schedule() and wrap() will return a promise, even if it failed with a synchronous exception. It is poor pra
schedule() and wrap() will return a promise, even if it failed with a synchronous exception. It is poor practice in JS to mix synchronous and asynchronous failures in the same flow. Few users will be affected by this change, and those who are affected will now benefit from more reliable code as a result.Thank you @elliot-nelson for this feature #116
Wrapped functions now inherit their this context. It allows for much nicer object-oriented code.
this context. It allows for much nicer object-oriented code.Thank you @elliot-nelson for this feature.
var object = {
value: "Hello World",
hello: limit.wrap(function () {
return this.value;
})
};
// When calling `object.hello()`, `this` = `object`
object.hello().then(console.log);
timeout events (Redis key TTL expiration) more efficiently.Fix an edge case when using Clustering at high load and/or in a large Cluster. A race condition could occur that left the data in a corrupted state.
Added limiter.clusterQueued(). Returns the total weight of queued jobs in the Cluster.
limiter.clusterQueued(). Returns the total weight of queued jobs in the Cluster.Fixed a memory leak that prevented limiters from being garbage collected until limiter.disconnect() was called.
limiter.disconnect() was called.Fixed an issue with Clustering, introduced in 2.14.0 or 2.15.1 depending on whether replication is being used, where it would not register that a clie
Fixed a script exception when using Redis Cluster. More information in this issue.
Added the 'failed' and 'retry' events. Bottleneck now support retries. See the Docs.
'failed' and 'retry' events. Bottleneck now support retries. See the Docs.Adds a light bundle and exposes Bottleneck's internal Events library. See https://github.com/octokit/plugin-throttling.js/pull/1#issuecomment-44966282
light bundle and exposes Bottleneck's internal Events library. See https://github.com/octokit/plugin-throttling.js/pull/1#issuecomment-449662827Clustering now spreads load evenly across instances in the Cluster
group.deleteKey(key) now deletes keys (across the Cluster) even if they are not present in the local Group instancegroup.clusterKeys(). Unlike group.keys(), it returns all Group keys in the Cluster, not just those in the local Group instance.Fixed an edge case where limiter.updateSettings() would fail when using Clustering and both maxConcurrent and reservoir are null after applying the ne
limiter.updateSettings() would fail when using Clustering and both maxConcurrent and reservoir are null after applying the new settings.Fixed a subtle memory leak due to a function scoping change. The issue was introduced in v2.10.0.
v2.10.0.v2.10.0 and tests have been added.Added support for ES5 in Bottleneck v2. import Bottleneck from "bottleneck/es5";
import Bottleneck from "bottleneck/es5";Added Bottleneck.BottleneckError to the TypeScript typings file.
Bottleneck.BottleneckError to the TypeScript typings file.Optimized and improved accuracy of Batching
Added new standalone feature called Batching. new Bottleneck.Batcher({ maxTime: 1000, maxSize: 25 }); See Documentation for more information.
new Bottleneck.Batcher({ maxTime: 1000, maxSize: 25 });
See Documentation for more information.Fixed Node process exiting early due to the reservoir reaching 0 when there are still queued jobs. This has been the source of much confusion for new
reservoir reaching 0 when there are still queued jobs. This has been the source of much confusion for new users.Fixed an issue with reservoir refresh where the very first refresh would happen too early.
reservoirRefreshInterval value as low as 250ms.Added the ability to manually control the creation and reuse of Redis connections via the connection option and the Bottleneck.RedisConnection and Bot
connection option and the Bottleneck.RedisConnection and Bottleneck.IORedisConnection objects.Added the done() method which returns the total weight of completed jobs across the Cluster.
done() method which returns the total weight of completed jobs across the Cluster.reservoirRefreshInterval, the reservoir value is automatically reset to reservoirRefreshAmount.Added support for pubsub across the Cluster. Use the publish() method and listen to the message event on a limiter.
publish() method and listen to the message event on a limiter.ready() promise to complete before issuing commands. The commands will be queued until the limiter successfully connects. Make sure to listen to the error event to handle connection errors.jobs() method to return a list of job ids in a specific state.check()) when a Group key is recreated after timing out.To use ioredis instead of Node Redis, pass the following option to Bottleneck: { datastore: "ioredis" }. ioredis supports Redis Cluster and Redis Sent
{ datastore: "ioredis" }. ioredis supports Redis Cluster and Redis Sentinel{ datastore: "redis", clusterNodes: [nodes] }. See the ioredis cluster docs and the Bottleneck docs for more informationFixed an issue where some limiter options were not properly marked as nullable.
Fixed a Clustering issue where limiters would sometimes fail with a NOSCRIPT error.
All limiters within a Group now share the same Redis connection. Standalone limiters continue to have their own limiters.
timeout option to limiters to allow freeing Redis state after a period of inactivity.Added support for passing job options to a wrapped function.
const wrapped = limiter.wrap(fn);
wrapped.withOptions(options, arg1, arg2);
All users are advised to upgrade to this version. There are no breaking changes.
Added the stop() method, which allows safely stopping a limiter and executing work once completed. See Readme.
stop() method, which allows safely stopping a limiter and executing work once completed. See Readme.Jobs with duplicate IDs are now rejected instead of throwing an exception.
Fixed a warning when using Webpack v4
.schedule().This release brings visibility into the status of limiters and jobs.
This release brings visibility into the status of limiters and jobs.
.counts() which returns an object with the number of jobs in every stage of their lifecycle..jobStatus(). It takes a jobId and returns the status of that job.trackDoneStatus, a new limiter option, defaulted to false. Setting it to true will make your limiter keep track of Done jobs in .counts() and .jobStatus(). It is false by default, since it involves remembering every jobId that has ever reached the Done stage, which could lead to a memory leak if your application processes tens or hundreds of millions of jobs between restarts.Fixed .on() and .once() not returning the object itself, which broke "chaining" and compatibility with Node's own events. Fixes #59 , thanks @bkw for
.on() and .once() not returning the object itself, which broke "chaining" and compatibility with Node's own events. Fixes #59 , thanks @bkw for the bug reportFixed an issue when using Clustering in a Group with maxConcurrent greater than 0 with jobs having an expiration time. A job timing out in a limiter i
maxConcurrent greater than 0 with jobs having an expiration time. A job timing out in a limiter in the group would lower the count of running jobs in all limiters in the group, which would result in going over the rate limit.schedule()Bottleneck v2 now ships code that is compatible with Node v6 instead of requiring Node v7.6. Thanks Babel.
depleted event now passes an empty argument.Added the depleted event. It is triggered when the reservoir reaches 0.
depleted event. It is triggered when the reservoir reaches 0.Fixed compilation when compiling using TypeScript and the --noImplicitAny compiler option
--noImplicitAny compiler optionThis new version is almost 100% compatible with Version 1 and it adds some powerful features such as:
This new version is almost 100% compatible with Version 1 and it adds some powerful features such as:
The internal algorithms essentially haven't changed from v1, but many small changes to the interface were made to introduce new features.
All the breaking changes:
submitPriority(), use submit() with an options object instead.schedulePriority(), use schedule() with an options object instead.rejectOnDrop option is now true by default.null instead of 0 to indicate an unlimited maxConcurrent value.null instead of -1 to indicate an unlimited highWater value.changeSettings() to updateSettings(), it now returns a promise to indicate completion. It takes the same options object as the constructor.nbQueued() to queued().nbRunning to running(), it now returns its result using a promise.isBlocked().changePenalty(), it is now done through the options object like any other limiter setting.changeReservoir(), it is now done through the options object like any other limiter setting.stopAll(). Use the reservoir feature to disable execution instead.check() now accepts an optional weight argument, and returns its result using a promise.Cluster feature is now called Group. This is to distinguish it from the new v2 Clustering feature.Group constructor takes an options object to match the limiter constructor.Group changeTimeout() method to updateSettings(), it now takes an options object.Version 2 is more user-friendly, powerful and reliable.
Added TypeScript type definitions thanks to @alexperovich
Cluster.changeTimeout()Propagate the arguments coming from promise()/promisePriority() into the task runner so that the dropped event shows the arguments that were given to
promise()/promisePriority() into the task runner so that the dropped event shows the arguments that were given to Bottleneck.Changed internal representation of jobs tracking from a sparse array to an object. Fixes #25
submit/submitPriority/schedule/schedulePriority, stopAll() now makes those functions automatically reject any new requests with a descriptive error. This should save a lot of frustration and help users debug their programs.Added the idle event. It is emitted when both nbQueued() and nbRunning() drop to 0, which means there is nothing running and nothing queued up.
idle event. It is emitted when both nbQueued() and nbRunning() drop to 0, which means there is nothing running and nothing queued up.removeAllListeners() method which follows the same pattern as the standard Node.js method of the same name. It supports an optional event name as first argument.nbRunning() method which returns the number of requests currently running in the limiter.Fixed an issue where the callback arguments when using rejectOnDrop with submit and submitPriority would be shifted when the job would be dropped.
rejectOnDrop with submit and submitPriority would be shifted when the job would be dropped.Added a new constructor parameter: rejectOnDrop. When set to true, dropped jobs will be failed/rejected with the Error This job has been dropped by Bo
rejectOnDrop. When set to true, dropped jobs will be failed/rejected with the Error This job has been dropped by Bottleneck.Default highWater value went from 0 (unlimited) to -1 (unlimited). This makes it possible to create limiters that drop anything that would have gone i
0 (unlimited) to -1 (unlimited). This makes it possible to create limiters that drop anything that would have gone into the queue, in order words setting highWater to 0 will create a limiter that will only accept requests that will be executed immediately.- Added .on('empty', callback) - Added .on('dropped', callback)
.on('empty', callback).on('dropped', callback)Bottleneck.Promise = ... --> Bottleneck.prototype.Promise
Bottleneck.Promise = ... --> Bottleneck.prototype.PromiseFixed bug #8 thanks to @albertreed
Fixed bug #8 thanks to @albertreed
Added strategy OVERFLOW_PRIORITY
submitPriority()schedulePriority()nbQueued()hasJobs()OVERFLOW_PRIORITYArray to a custom very efficient data structure, see DDList.coffee, especially with over 1,000 jobs in a limiter.Fixed Promise issue on Node 0.10 when bluebird isn't installed.
- Added stopAutoCleanup() - Added startAutoCleanup() - Added deleteKey()
stopAutoCleanup()startAutoCleanup()deleteKey()Bottleneck now uses Bluebird by default and falls back to the native Promise object if Bluebird is unavailable.
Your coding agent can read these notes before it upgrades. Set up the MCP server →