nx_rate_limit_v1.nx
buildroot/runtime/nx_rate_limit_v1.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: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 39 | struct RateLimiter |
consts
| 36 | const RL_MAGIC_500000: i64 = 500000 |
| 37 | const RL_MAGIC_5500000: i64 = 5500000 |
| 47 | const RL_SCALE: i64 = 1000000 |
functions
| 51 | func rate_limit_init(rl: *RateLimiter, capacity: i64, called by 1: main |
| 62 | func rate_limit_refill(rl: *RateLimiter, now_us: i64) -> i64 |
| 77 | func rate_limit_try_take(rl: *RateLimiter, n: i64, now_us: i64) -> i64 |
| 86 | func rate_limit_available(rl: *RateLimiter, now_us: i64) -> i64 |
| 93 | func rate_limit_next_token_us(rl: *RateLimiter, now_us: i64) -> i64 |
| 106 | func main() -> i64 |