Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
117 committed Sep 22, 2024
0 parents commit a673859
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: deploy
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: set up Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: run Deno tests
run: deno test
- name: publish to JSR
run: npx jsr publish
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# throttle

![version](https://img.shields.io/jsr/v/%40117/throttle?style=flat-square&color=%23ff51bc&label=version)
![status](https://img.shields.io/github/actions/workflow/status/117/throttle/deploy.yml?style=flat-square)

A throttle function implementation for Deno that manages request rates.

## Contents

- [Features](#features)
- [Install](#install)
- [Example](#example)
- [Contributing](#contributing)

## Features

- [x] Simple and easy to use.
- [x] Regulates access to functions based on defined limits.

## Install

For Deno:

```sh
$ deno add @117/throttle
```

## Example

```ts
import { createThrottle } from "@117/throttle";

const throttle = createThrottle({ limit: 5, interval: 1000 });

const work = () => {
if (throttle.canProceed()) {
console.log("request allowed, processing work");
} else {
console.log("request blocked, please wait");
}
};

// Simulate requests
setInterval(work, 200);
```

## Contributing

Feel free to contribute and PR to your 💖's content.
10 changes: 10 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@117/throttle",
"description": "A token bucket rate limiter for Deno.",
"version": "1.0.0",
"exports": "./mod.ts",
"imports": {
"@/": "./",
"assert": "https://deno.land/std@0.224.0/assert/mod.ts"
}
}
9 changes: 9 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
createThrottle,
type CreateThrottleOptions,
} from "@/src/createThrottle.ts";
31 changes: 31 additions & 0 deletions src/createThrottle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type CreateThrottleOptions = {
limit: number;
interval: number;
};

export const createThrottle = ({ limit, interval }: CreateThrottleOptions) => {
let tokens = limit;
let lastRefill = Date.now();

const refillTokens = () => {
const now = Date.now();
const elapsed = now - lastRefill;
const newTokens = Math.floor(elapsed / interval) * limit;

tokens = Math.min(limit, tokens + newTokens);
lastRefill = now;
};

const canProceed = () => {
refillTokens();

if (tokens > 0) {
tokens--;
return true;
}

return false;
};

return { canProceed };
};
26 changes: 26 additions & 0 deletions src/createThrottle_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { assert } from "https://deno.land/std@0.177.0/testing/asserts.ts";
import { createThrottle } from "./createThrottle.ts";

Deno.test("should allow requests within limit", () => {
const throttle = createThrottle({ limit: 5, interval: 1000 });

for (let i = 0; i < 5; i++) {
assert(throttle.canProceed(), `request ${i + 1} should be allowed`);
}
});

Deno.test("should block requests exceeding limit", async () => {
const throttle = createThrottle({ limit: 2, interval: 1000 });

assert(throttle.canProceed(), "first request should be allowed");
assert(throttle.canProceed(), "second request should be allowed");
assert(!throttle.canProceed(), "third request should be blocked");

// Wait for the interval to pass
await new Promise((resolve) => setTimeout(resolve, 1000));

assert(
throttle.canProceed(),
"fourth request should be allowed after interval",
);
});

0 comments on commit a673859

Please sign in to comment.