A promise pool with RPS limiter.
Find a file
Anton Nesterov 2550f7e165 [fix] readme
2024-07-11 01:36:44 +02:00
.github/workflows [fix] readme 2024-07-11 01:36:44 +02:00
dist add jsr 2024-07-11 01:20:10 +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
limiter.test.ts init 2024-07-11 01:14:10 +02:00
limiter.ts add jsr 2024-07-11 01:20:10 +02:00
package.json [fix] readme 2024-07-11 01:36:44 +02:00
README.md [fix] readme 2024-07-11 01:36:44 +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

Usage

Add tasks

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

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

const limiter = new Limiter({
  limit: 20,
  onError(error) {
    // Logger.error(error)
  },
});

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

Limit number of requests

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

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

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

await limiter.process(...Array.from({ length: 100 }, () => task()));

Limit RPS

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

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

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

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");
  // ... write
};

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)
    }
  }
}

Handle errors in background

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

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

const limiter = new Limiter({
  limit: 20,
  maxRetry: 5,
  onError(error) {
    // Logger.error(error)
  },
});

for (let i = 0; i < 100; i++) {
  await limiter.process(Array.from({ length: 100 }, () => wontStopPooling()));
}