SGrondin / bottleneck

Job scheduler and rate limiter, supports Clustering
MIT License
1.83k stars 79 forks source link

The Reservoir Interval starts from the moment the limiter is created #153

Open dutu opened 4 years ago

dutu commented 4 years ago

I'm running into the issue described in the documentation:

Let's suppose we're using reservoirRefreshAmount: 5. If you happen to add 10 jobs just 1ms before the refresh is triggered, the first 5 will run immediately, then 1ms later it will refresh the reservoir value and that will make the last 5 also run right away. It will have run 10 jobs in just over 1ms no matter what your reservoir interval was!

To overcome the issue, i.e. prevent running more than 5 jobs over a certain interval (say 1 minute), I'm using the code below:

const interval = 60 * 1000
const limiter = new Bottleneck({ maxConcurrent: 1, minTime: 1, reservoir: 5 })
limiter.on('executing', (info) => {
      setTimeout(() => limiter.incrementReservoir(1), interval)
})

Do you see any issue with this approach or do you have any other suggestion?

yairopro commented 2 years ago

I'm just sharing my solution here for this same problem.

const count = 25, time = 1000; // 25 requests per second

const bottleneck = new Bottleneck({ reservoir: count });
bottleneck.on("executing", ({ options }) => {
    const weight = options.weight || 1;
    if (weight >= 1)
        setTimeout(() => bottleneck.incrementReservoir(weight), time);
});