nopanic-redis
Redis-backed circuit breakers and rate limits for nopanic, shared by every process and host that uses them.
pip install nopanic-redis
A nopanic.circuit_breaker lives in one process. Behind a load balancer with 40 workers, each worker has to discover a dead dependency on its own, and a rate_limit(100) lets 4,000 calls through. These policies keep that state in Redis, so the fleet trips together and shares one quota:
import redis
from nopanic_redis import redis_circuit_breaker, redis_rate_limit
r = redis.Redis() # redis.asyncio.Redis() for async functions
payments = redis_circuit_breaker(r, name="payments", min_calls=20, reset_timeout=15.0)
openai_quota = redis_rate_limit(r, name="openai", rate=500, per=60.0, max_wait=5.0)
@openai_quota
@payments
def charge(order): ...
Semantics
- Same model as the in-process policies.
redis_circuit_breakertakes the parameters ofnopanic.CircuitBreaker(failure-rate threshold over a bucketed sliding window,min_calls,reset_timeout,half_open_max_calls,on).redis_rate_limitisnopanic.rate_limit(token bucket,burst, waiting by default,RateLimited(retry_after=...)withmax_wait, ambientdeadlinerespected, cancelled waiters refunded). - Identity is the name. Every instance with the same
nameandprefixis the same breaker or bucket, whichever process created it. Keys use a Redis Cluster hash tag, so each policy's keys stay in one slot. - Atomic and cheap. Each decision is one Lua script, one round trip: a breaker costs two per call (admit, record), a rate limit one.
- Clocks. Time comes from the callers' wall clocks (
time.time, injectable viaclock=); keep hosts NTP-synced. Skew only shifts window boundaries slightly. - Redis down is not your outage. With
fail_open=True(default) calls go through unguarded and abreaker.store_error/ratelimit.store_errorevent is emitted;fail_open=Falserejects withCircuitOpen/RateLimitedinstead. - Sync or async by client. A
redis.Redisclient serves sync functions, aredis.asyncio.Redisclient serves async ones (use two instances with the same name to guard both; they share state). breaker.get_state()andbreaker.reset()act fleet-wide (awaitable with an async client). Streams are not supported.
Events are the usual nopanic events, so nopanic-otel and events.log_to work unchanged.
License
MIT.
Metadata
Release files for nopanic-redis 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nopanic_redis-0.1.0.tar.gz | 10.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nopanic_redis-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.9 kB
Release files / nopanic_redis-0.1.0.tar.gz
| Download URL | nopanic_redis-0.1.0.tar.gz |
|---|---|
| Size | 10.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
673bd17d5add9457c15ff6eaf85f849e6656808a950e870d97e276d62f95b4bd
|
|
BLAKE2b-256 checksum How to use checksums |
9b410170b8f40684acd44c4c1561947c8e38a7a523913dc2c650fda464a6da84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.6
|
Release files / nopanic_redis-0.1.0-py3-none-any.whl
| Download URL | nopanic_redis-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
37e6670b0dfba42ad588d816eba2671a6be5af1d9b3ccfecace8242454766990
|
|
BLAKE2b-256 checksum How to use checksums |
f66e902a398807b5ab2e561f2dbfe426a7ee113d8b73584b2c8c288ed4fbe3fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.6
|