rate_limit.nx
buildroot/runtime/rate_limit.nx
about
rate_limit.nx -- token-bucket rate limiter.
Standard algorithm (RFC 2698 / IEEE; also what HAProxy, nginx,
AWS API Gateway, and Stripe use):
- Bucket has a max capacity (burst size) of B tokens
- Tokens refill at rate R per second up to B
- Each request consumes 1 token (or more for weighted ops)
- Request allowed iff current tokens >= needed; otherwise
reject (429 Too Many Requests) or wait
Time is passed in as unix_microseconds -- caller reads a
monotonic clock and hands it to us. This keeps the module
pure + testable and decoupled from the OS time source.
For real use pair with ntp.nx + sys_clock_monotonic.
Use cases: HTTP API throttling (per IP / per token), login
attempt rate limiting (anti-brute-force), outbound API call
pacing, mail-send pacing, git clone pacing.
Invariants:
RL1 tokens clamped to capacity on every refill (bucket
never overflows).
RL2 Time going backwards does nothing (malicious / NTP
adjustment) -- we record max(now, last_refill).
RL3 Rate is expressed in tokens per second; sub-second
granularity handled via microsecond timestamps.
dependencies 1 imports · 0 importers
imports: syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 31 | struct RateLimiter { |
consts
| 39 | const RL_SCALE: i64 = 1000000 |
functions
| 43 | func rate_limit_init(rl: *RateLimiter, capacity: i64,
called by 1: main |
| 54 | func rate_limit_refill(rl: *RateLimiter, now_us: i64) -> i64 { |
| 69 | func rate_limit_try_take(rl: *RateLimiter, n: i64, now_us: i64) -> i64 { |
| 78 | func rate_limit_available(rl: *RateLimiter, now_us: i64) -> i64 { |
| 85 | func rate_limit_next_token_us(rl: *RateLimiter, now_us: i64) -> i64 { |
| 98 | func main() -> i64 { |