Files
skills/docs/foundation/flow/streams-chunk-queue/src/rate-limiter/adapter.md
2026-05-29 08:20:56 +01:00

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, using retryAfter when 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.