Skip to content

v0.149.0

Choose a tag to compare

@nstfkc nstfkc released this 17 Oct 19:23
· 120 commits to main since this release

Redis: the shared client reconnects after an outage, and RedisRateLimiter has a timeout (#982)

Behaviour change. Nothing to migrate. See Middleware → Rate limiting and Facades → Redis.

  • Before, once Bun's Redis client gave up on a connection (a connect timeout, or maxRetries reconnects), it never connected again and RedisManager kept handing it out. Every Redis command then failed until the process restarted, and RedisRateLimiter with failOpen (the default) turned every limit off.
  • RedisManager.client now replaces a client that is down: it closes it and builds a new one. Down means not connected, and not still making the first connection the manager started for it (building a client now starts connecting it; a connect pending past connectionTimeout + 5 s counts as failed). It waits 0.5 s first, so a blip Bun's own reconnect covers costs nothing; the wait doubles to 10 s with each new client that fails to connect and resets once one connects. This covers everything on the shared connection: the Redis facade, RedisRateLimiter, the "redis" cache store, RedisNonceStore, RedisReceiptStore. A client you pass to one of them yourself (new RedisRateLimiter({ client })) is not covered.
  • Read Redis.client (or RedisManager.client) each time instead of keeping it: a kept reference may be a client that was replaced and closed. Calling connect() again on Bun's failed client is not a fix: on some Bun versions (1.3.x on Linux) it never settles.
  • RedisRateLimiter takes timeout (ms, default 250, 0 turns it off). A call that runs past it follows failOpen/failClosed at once and reports a RedisRateLimiterTimeoutError (new export of gemi/services) to onError. Before, a limited request could wait 10 to 30 s during an outage, and with no limit when Redis stopped answering on an open connection. Redis may still run a script that timed out, so that call can still be counted. Raise timeout if your Redis is far from the app (a cross-region round trip near 250 ms would fail open or closed on every call).