2.4 KiB
rate-limiter / adapter
(no submodules)
Purpose
Normalises the @suaveplan/rate-limiter TokenBucket API onto
the ChunkRateLimiter interface used internally by the streaming chunk
queue. The TokenBucket does NOT throw on denial — it returns
{ allowed: boolean, retryAfter?: number }. This adapter encodes the
denial branch into the canonical { allowed: false, delay } shape the
queue understands, with a configurable fallback when retryAfter is
missing.
Features
- Wraps any structurally compatible
TokenBucketLike. - Returns
{ allowed: true, delay: 0 }on admission. - Returns
{ allowed: false, delay }on denial, usingretryAfterwhen positive or a configurable fallback (default 100 ms) otherwise. - Stateless beyond the bucket reference — safe to share across queues.
Usage: Basic
import { TokenBucket } from "@suaveplan/rate-limiter";
import { TokenBucketRateLimiterAdapter } from "@suaveplan/streams-chunk-queue";
const bucket = new TokenBucket({ capacity: 1024 * 1024, refillRate: 1024 });
const limiter = new TokenBucketRateLimiterAdapter(bucket);
Usage: Advanced
// Aggressive fallback for tightly-bound real-time streams.
const limiter = new TokenBucketRateLimiterAdapter(bucket, 25);
API Reference
ChunkRateLimiter
interface ChunkRateLimiter {
consume(bytes: number): { allowed: boolean; delay: number };
}
TokenBucketLike
Structural subset of the TokenBucket:
interface TokenBucketLike {
consume(tokens?: number): { allowed: boolean; retryAfter?: number };
}
TokenBucketRateLimiterAdapter
new TokenBucketRateLimiterAdapter(
bucket: TokenBucketLike,
fallbackDelayMs?: number, // default 100
)
consume(bytes) calls bucket.consume(bytes) and normalises the
result. The fallback delay is used only when the bucket denies AND
omits / zeroes retryAfter.
DEFAULT_RATE_LIMIT_DELAY_MS
The constant 100. Exposed for callers who want to reuse the default
in their own diagnostics.
Implementation Notes
The structural TokenBucketLike keeps @suaveplan/rate-limiter an
optional peer concern at the type boundary — tests inject a fake
bucket and never need to spin up the real one. The adapter does not
sleep itself; the queue is in charge of timing because it owns the
onRateLimit hook and the rate:limited event.