A promise pool with RPS limiter.
Find a file
2024-07-11 17:09:29 +02:00
.github/workflows [fix] readme 2024-07-11 01:36:44 +02:00
dist [feat] add done() callback 2024-07-11 17:09:29 +02:00
.gitignore init 2024-07-11 01:14:10 +02:00
bun.lockb init 2024-07-11 01:14:10 +02:00
jsr.json [fix] readme 2024-07-11 01:36:44 +02:00
LICENSE [feat] add done() callback 2024-07-11 17:09:29 +02:00
limiter.test.ts [feat] add done() callback 2024-07-11 17:09:29 +02:00
limiter.ts [feat] add done() callback 2024-07-11 17:09:29 +02:00
package.json [fix] readme 2024-07-11 01:36:44 +02:00
README.md [feat] add done() callback 2024-07-11 17:09:29 +02:00
tsconfig.json init 2024-07-11 01:14:10 +02:00

Limiter

A promise pool with RPS limiter.

Features:

  • TypeScript first
  • Limits parrallel promises execution
  • Limits RPS (requests per second), evenly distributes the requests over time
  • Able to retry
  • Simple API
  • Simple async/await flow
  • Allows to handle errors silently using onError callback
  • Works with any runtime (Bun/Deno/Node)

Install

bun add github:nesterow/limiter # or pnpm

API

  • limit - default 10
  • maxRetry - number of retries, use Infinity to retry until dead
  • rps - if set throttles task execution based on provided rate per second
  • onError() - if set, the errors are handled silently
limiter = new Limiter({
  limit?: number;
  maxRetry?: number;
  rps?: number;
  onError?: (error: Error) => Promise<void> | void;
})

Usage

Add tasks

import { Limiter } from "@nesterow/limiter";

const limiter = new Limiter({
  limit: 20,
});

const task = () => {
  await fetch(url);
};

limiter.process(task);
limiter.process(task);
limiter.process(task);

await limiter.done()

Batch processing

import { Limiter } from "@nesterow/limiter";

const task = () => {
  await fetch("https://my.api.xyz");
};

const limiter = new Limiter({
  limit: 10,
});

// process 100 tasks, 10 at the same time
await limiter.process(...Array.from({ length: 100 }, () => task()));

Limit RPS

import { Limiter } from "@nesterow/limiter";

const execEvery100ms = () => {
  await fetch("https://my.api.xyz");
};

const limiter = new Limiter({
  limit: 20,
  rps: 10,
});

// trottle every 100ms
await limiter.process(...Array.from({ length: 100 }, () => execEvery100ms()));

Retry

import { Limiter, LimiterRetryError } from "@nesterow/limiter";

const retry5times = () => {
  await fetch("https://my.api.xyz");
  throw new Error("Connection refused");
};

const limiter = new Limiter({
  limit: 20,
  maxRetry: 5,
});

for (let i = 0; i < 100; i++) {
  try {
    await limiter.process(...Array.from({ length: 100 }, () => retry5times()));
  } catch (e) {
    if (e instanceof LimiterRetryError) {
      // Logger.log(e)
    }
  }
}

License

MIT