feat(19.3-01): share rate limits across instances through cooler's Redis store

- new module cooler: Install, Handle, OpenRedis (no URL in errors), RateLimitStore
  (atomic fixed-window Lua script with MemoryStore semantics, per-instance fallback)
- serve installs cooler and publishes the Redis surf.Store before BuildRouter;
  BuildRouter looks up a published Store, route:list keeps the memory store
- config keys http.rate_limit.store and redis.url; go-redis v9.23.0
- cooler README, root table row, surf README and rate-limiting, configuration
  and scaling docs
This commit is contained in:
Jakub Zych
2026-10-15 17:34:39 +02:00
parent 77dd11c804
commit fa4d89d0b9
15 changed files with 777 additions and 10 deletions

View File

@@ -472,8 +472,19 @@ func BuildRouter(app *backpack.App, plugins []party.Plugin) (*Router, error) {
if app != nil {
trusted = TrustedProxies(app.Config)
}
// longest bucket decay is 1 minute; sweep at 2x
lim := NewFixedWindowLimiter(NewMemoryStore(2*time.Minute), trusted)
// serve publishes a shared Store (cooler's Redis store) before building
// the router; route:list and tests get the in-process MemoryStore.
var store Store
if app != nil {
if s, ok := app.Lookup[Store](); ok && s != nil {
store = s
}
}
if store == nil {
// longest bucket decay is 1 minute; sweep at 2x
store = NewMemoryStore(2 * time.Minute)
}
lim := NewFixedWindowLimiter(store, trusted)
r.limiter = lim
if err := r.RegisterMiddlewareFactory("surf", "throttle", func(param string) pact.Middleware {
return lim.Middleware(param)