Algorithm-RateLimiter-TokenBucket

 view release on metacpan or  search on metacpan

CODE_OF_CONDUCT.md  view on Meta::CPAN

posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://github.com/sanko/Net-BitTorrent.pm/discussions.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed

CONTRIBUTING.md  view on Meta::CPAN


    ```bash
    # For a new feature:
    git checkout -b feature/add-riscv-support
    # For a bug fix:
    git checkout -b fix/struct-classification-bug
    ```

4.  **Make Your Changes**: Write your code. Please adhere to the existing coding style and add comments to new or complex logic.
5.  **Test Your Changes**: A pull request is far more likely to be accepted if it includes tests. If you add new functionality, please add a corresponding test case.
6.  **Update the Changelog**: Add an entry to the `[Unreleased]` section of `CHANGELOG.md` describing your change.
7.  **Submit a Pull Request**: Push your branch to your fork and open a pull request against the `main` branch of the original repository. Please provide a clear description of your changes and link to the relevant issue (e.g., `Fixes #123`).

README.md  view on Meta::CPAN


`Algorithm::RateLimiter::TokenBucket` implements the [token bucket](https://en.wikipedia.org/wiki/Token_bucket)
algorithm for rate limiting. It is specifically designed to be **loop-agnostic**, meaning it does not manage its own
timers or background threads. Instead, you "drive" it by calling `tick( )` with the amount of time that has passed.

This makes it ideal for integration into event loops (like [IO::Async](https://metacpan.org/pod/IO%3A%3AAsync) or [Mojo::IOLoop](https://metacpan.org/pod/Mojo%3A%3AIOLoop)) or high-performance network
applications.

# METHODS

## `new( limit =` $bytes\_per\_second )>

Creates a new limiter. `limit` is optional and defaults to 0 (unlimited).

## `set_limit( $limit )`

Dynamically updates the rate limit.

## `tick( $delta_seconds )`

Adds new tokens to the bucket based on the time elapsed.

## `consume( $amount )`

Attempts to consume `$amount` units (tokens) from the bucket. Returns the number of units actually consumed.

## `available( )`

Returns the current number of tokens in the bucket.

SECURITY.md  view on Meta::CPAN

# Security Policy

Until I have the version 1.0.0 release, I'll support only the last two minor versions with security updates.

## Supported Versions

| Version    | Supported          |
| ---------- | ------------------ |
| v1.0.x     | :white_check_mark: |
| < v1.0.0   | :x:                |

# Reporting a Vulnerability

If you have any issue regarding security, please disclose the information responsibly by sending a report to the project's security advisory page and *not* at the public issue tracker or via email.

# Vulnerability Disclosure Policy

Maintaining the security of our open-source software is paramount. This policy outlines a responsible approach to addressing vulnerabilities, balancing transparency with the need to protect users.

- Security vulnerabilities identified in the project will be assigned a unique identifier and (if applicable) a Common Vulnerabilities and Exposures (CVE) identifier.

- The project's Maintainers will be responsible for addressing the vulnerability through a standard pull request, backporting the fix to immediate prior minor release branch, and including the fix in the next stable release.

- Release notes for the patched version will include the assigned identifier and, if applicable, the CVE identifier for the vulnerability.

- A grace period will be provided for Maintainers to update the vulerable minor version and remove vulerable releases from PAUSE (nothing can be done about backpan).

  This period will be one month for non-critical vulnerabilities and three months for critical vulnerabilities.

lib/Algorithm/RateLimiter/TokenBucket.pm  view on Meta::CPAN

use v5.40;
use feature 'class';
no warnings 'experimental::class';
#
class Algorithm::RateLimiter::TokenBucket v1.0.0 {
    field $limit : param : reader //= 0;    # Bytes per second, 0 = unlimited
    field $tokens : reader = $limit;
    field $max_burst = $limit * 2;          # Allow some burst, but not too much

    #
    method set_limit ($new_limit) {
        $limit     = $new_limit;
        $max_burst = $limit * 2;
    }

    method tick ($delta) {

lib/Algorithm/RateLimiter/TokenBucket.pod  view on Meta::CPAN


C<Algorithm::RateLimiter::TokenBucket> implements the L<token bucket|https://en.wikipedia.org/wiki/Token_bucket>
algorithm for rate limiting. It is specifically designed to be B<loop-agnostic>, meaning it does not manage its own
timers or background threads. Instead, you "drive" it by calling C<tick( )> with the amount of time that has passed.

This makes it ideal for integration into event loops (like L<IO::Async> or L<Mojo::IOLoop>) or high-performance network
applications.

=head1 METHODS

=head2 C<new( limit => $bytes_per_second )>

Creates a new limiter. C<limit> is optional and defaults to 0 (unlimited).

=head2 C<set_limit( $limit )>

Dynamically updates the rate limit.

=head2 C<tick( $delta_seconds )>

Adds new tokens to the bucket based on the time elapsed.

=head2 C<consume( $amount )>

Attempts to consume C<$amount> units (tokens) from the bucket. Returns the number of units actually consumed.

=head2 C<available( )>

Returns the current number of tokens in the bucket.

t/basics.t  view on Meta::CPAN

    isa_ok my $rl = Algorithm::RateLimiter::TokenBucket->new( limit => 1000 ), ['Algorithm::RateLimiter::TokenBucket'];
    is $rl->consume(400),  400, 'Consumed 400 tokens';
    is $rl->available,     600, '600 tokens remaining';
    is $rl->consume(1000), 600, 'Requested 1000, only got remaining 600';
    is $rl->available,     0,   'Bucket now empty';
};
subtest 'Ticking (Accumulation)' => sub {
    isa_ok my $rl = Algorithm::RateLimiter::TokenBucket->new( limit => 1000 ), ['Algorithm::RateLimiter::TokenBucket'];
    ok $rl->consume(1000), 'consume( 1000 )';
    is $rl->available, 0, 'Started empty';
    note 'tick( 0.5 )';    # Tick 0.5 seconds -> should add 500 tokens
    $rl->tick(0.5);
    is $rl->available, 500, 'Added 500 tokens after 0.5s';
    note 'tick( 2.0 )';    # Tick another 1.0 seconds -> should hit max_burst (limit * 2 = 2000)
    $rl->tick(2.0);
    is $rl->available, 2000, 'Capped at max_burst (2000)';
};
subtest 'Dynamic Limit Updates' => sub {
    isa_ok my $rl = Algorithm::RateLimiter::TokenBucket->new( limit => 1000 ), ['Algorithm::RateLimiter::TokenBucket'];
    ok $rl->set_limit(5000), 'set_limit( 5000 )';
    is $rl->limit, 5000, 'limit updated';
    ok $rl->consume(5000), 'consume( 5000 )';    # Simulate an initial burst
    note 'tick( 1.0 )';
    $rl->tick(1.0), is $rl->available, 5000, 'accumulated at new rate';



( run in 0.626 second using v1.01-cache-2.11-cpan-39bf76dae61 )