build(deps): bump actions/checkout from 4.1.7 to 7.0.0 - #1173
Merged
Merged
Conversation
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
collin-lee
approved these changes
Jul 6, 2026
There was a problem hiding this comment.
Pull request overview
This PR updates the pinned actions/checkout GitHub Action used across the repository’s workflows from v4.1.7 to v7.0.0 (by commit SHA), keeping CI/security workflows current and aligned with upstream changes.
Changes:
- Bump
actions/checkoutpin to9c091bb...(v7.0.0) in all workflows that perform repository checkout. - Keep the existing pinned-by-SHA pattern and update the inline version comments accordingly.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/scorecard.yml | Updates checkout step to actions/checkout v7.0.0. |
| .github/workflows/release.yaml | Updates checkout steps in release tag workflow to v7.0.0. |
| .github/workflows/pullrequest.yaml | Updates checkout steps in PR CI workflow to v7.0.0. |
| .github/workflows/main.yaml | Updates checkout steps in main branch CI workflow to v7.0.0. |
| .github/workflows/codeql.yml | Updates checkout step in CodeQL analysis workflow to v7.0.0. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dependabot
Bot
deleted the
dependabot/github_actions/actions/checkout-7.0.0
branch
July 6, 2026 06:41
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (envoyproxy#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (envoyproxy#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (envoyproxy#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (envoyproxy#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (envoyproxy#1196) Follow-up to envoyproxy#1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after envoyproxy#1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (envoyproxy#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (envoyproxy#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@49b3bc8...96fe6ef) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (envoyproxy#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@692973e...9c091bb) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (envoyproxy#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (envoyproxy#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (envoyproxy#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (envoyproxy#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (envoyproxy#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (envoyproxy#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (envoyproxy#1148) feat: add retry in init phase instead of panic directly (envoyproxy#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (envoyproxy#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (envoyproxy#1131) PR envoyproxy#1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (envoyproxy#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (envoyproxy#1110) Fix Prometheus response time units (envoyproxy#1104) Dockerfile: add ENTRYPOINT (envoyproxy#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (envoyproxy#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (envoyproxy#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (envoyproxy#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (envoyproxy#1091) Add integration test for token based quota (envoyproxy#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (envoyproxy#1090) Add debug logging for quota values (envoyproxy#1089) Wait for sevices to be up before running tests (envoyproxy#1088) update otel and fix failing tests (envoyproxy#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (envoyproxy#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (envoyproxy#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (envoyproxy#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (envoyproxy#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (envoyproxy#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (envoyproxy#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (envoyproxy#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (envoyproxy#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (envoyproxy#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (envoyproxy#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (envoyproxy#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (envoyproxy#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (envoyproxy#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (envoyproxy#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (envoyproxy#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (envoyproxy#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (envoyproxy#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (envoyproxy#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oclaw
added a commit
to oclaw/ratelimit
that referenced
this pull request
Aug 20, 2026
A counter that goes over the limit poisons the local cache of the replica that observed it, and a refund that brings the counter back under the limit previously left every replica answering OVER_LIMIT from the local cache until the window ended. With the Redis backend, the decrement script now publishes the cache key on the ratelimit:local_cache_invalidation pub/sub channel when a refund crosses the counter back under its limit (old > limit && new <= limit), keeping the publish rate at one message per poisoning cycle. Every replica running with negative hits and a local cache subscribes on one dedicated connection to the main Redis and deletes published keys from its freecache, reconnecting with exponential backoff (capped at 30s) on connection errors. Invalidation is best-effort / at-most-once: missed messages are never buffered or replayed. Decrements routed to the dedicated per-second Redis never publish since the subscriber listens only on the main Redis. New statistics: ratelimit.localcache.invalidation.subscribed (gauge), .received and .deleted (counters). Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.rate_limit.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add ENABLE_NEGATIVE_HITS flag gating the negative-hits feature Negative hits (is_negative_hits descriptors) are now gated by the ENABLE_NEGATIVE_HITS environment variable, default off. While the flag is off, any request containing a negative-hit descriptor is rejected as a whole with the gRPC UNIMPLEMENTED code before the cache call, so a negative-hit descriptor is never silently processed as a positive hit. Rejections are counted in the new ratelimit.service.negative_hits_rejected statistic. The combination negative hits + memcached + local cache refuses to boot: an over-limit counter poisons the local cache and there is no invalidation path for memcached. All other combinations boot as before, including memcached negative hits without local cache. Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to the corresponding multi-arch index digest sha256:b54cbf583d39 0341599d7bcbc062425c081105cc5ef6d170ced98ef9d047c716, which contains the existing 7095ad02... amd64 manifest as one of its children plus the arm64/v8 and other platform variants. The amd64 image is unchanged; arm64 builds now produce arm64 binaries. Signed-off-by: Harrison Harris <harrison.harris@xapien.com> Co-authored-by: Harrison Harris <harrison.harris@xapien.com> Update third party libraries flagged for vulnerability scans (#1124) Signed-off-by: collin-lee <collin.lee@salesforce.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: add zipkin b3 header propagation (#1110) Fix Prometheus response time units (#1104) Dockerfile: add ENTRYPOINT (#1095) Make the docker image easier to consume. Signed-off-by: Ian Kerins <git@isk.haus> Send user defined metadata to the client (#1112) Signed-off-by: Yan Avlasov <yavlasov@google.com> build(deps): bump google.golang.org/grpc from v1.74.2 to v1.80.0 (#1111) Signed-off by: João Pereira <joao@jpereira.me> Upgrades the gRPC dependency from v1.74.2 to v1.80.0, along with its transitive dependency updates (golang.org/x/net, google.golang.org/protobuf, genproto, go-control-plane, etc.). Signed-off-by: João Pereira <joao.pereira@zwift.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Fix quota result when all limits were exceeded (#1059) * Fix quota result when all limits were exceeded Signed-off-by: yavlasov <yavlasov@google.com> * Address comments Signed-off-by: yavlasov <yavlasov@google.com> * Fix comment Signed-off-by: yavlasov <yavlasov@google.com> * fix comment Signed-off-by: yavlasov <yavlasov@google.com> * Remove log into a file Signed-off-by: yavlasov <yavlasov@google.com> --------- Signed-off-by: yavlasov <yavlasov@google.com> Update golang references to 1.26.1 (#1091) Add integration test for token based quota (#1092) Signed-off-by: yavlasov <yavlasov@google.com> Add quota integration test (#1090) Add debug logging for quota values (#1089) Wait for sevices to be up before running tests (#1088) update otel and fix failing tests (#1078) Signed-off-by: Ashish Tiwari <ashishjaitiwari15112000@gmail.com> feat: Support wildcard in non-trailing positions for rate limit descriptor values (#1085) Signed-off-by: Nam Dang <xuannam230201@gmail.com> build(deps): bump golang from 1.25.6 to 1.26.1 (#1079) Bumps golang from 1.25.6 to 1.26.1. --- updated-dependencies: - dependency-name: golang dependency-version: 1.26.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bump go version 1.25.6 (#1047) Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> implement quota mode for soft rate limit check (#1045) * implement quota mode for rate limit check Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix format Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix tests Signed-off-by: Dan Sun <dsun20@bloomberg.net> * fix quota mode flag Signed-off-by: Dan Sun <dsun20@bloomberg.net> --------- Signed-off-by: Dan Sun <dsun20@bloomberg.net> upgrade radix from v3 to v4 for improved pipeline handling (#1041) * feat: upgrade radix from v3 to v4 Upgrade radix Redis client from v3.8.1 to v4.1.4. Main changes: - Import paths: radix/v3 -> radix/v4 - Pool/Cluster/Sentinel use Config.New() instead of New() - All client operations require context.Context parameter - Dialer setup changed from functional options to struct config - Pipelining uses radix.NewPipeline() and Append() - Write buffering via Dialer.WriteFlushInterval Breaking from v3: - Pool on-empty behavior (WAIT/CREATE/ERROR) not available - REDIS_PIPELINE_LIMIT setting deprecated (no effect in v4) Tested with existing test suite - all tests passing. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: update pipeline settings for radix v4 Update documentation to reflect radix v4's pipeline behavior: - REDIS_PIPELINE_WINDOW now sets WriteFlushInterval (auto-flush timing) - REDIS_PIPELINE_LIMIT deprecated - no effect in v4 - Add REDIS_USE_EXPLICIT_PIPELINE for manual pipeline control - Required for Redis Cluster: PIPELINE_WINDOW must be non-zero Update terminology from "implicit pipelining" to "write buffering" to better match radix v4's actual behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: update tests for radix v4 - Add useExplicitPipeline parameter to test client creation - Update error assertions for v4's error message format (v4 prefixes with "response returned from Conn:") - Handle different connection errors (EOF, connection reset, broken pipe) - Update radix.FlatCmd usage for v4 API Signed-off-by: seonghyun <seonghyunoh@gmail.com> * chore: add deprecation warning for REDIS_PIPELINE_LIMIT Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix Redis cluster test config for radix v4 Replace deprecated RedisPipelineLimit with RedisPipelineWindow in configRedisCluster function. Radix v4 requires WriteFlushInterval (RedisPipelineWindow) for cluster mode buffering instead of the deprecated pipeline limit setting. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt struct field alignment in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: fail fast on unsupported REDIS_POOL_ON_EMPTY_BEHAVIOR settings Radix v4 does not support CREATE or ERROR behaviors for REDIS_POOL_ON_EMPTY_BEHAVIOR. Previously, these settings were logged as errors but the application would continue with blocking behavior, which could cause unexpected issues in production. Changes: - Panic at startup when CREATE or ERROR is detected - Prevent silent behavior changes that could cause blocking - Update tests to verify panic behavior - Improve migration documentation in comments This ensures users are immediately notified of incompatible configuration rather than experiencing unexpected blocking in production. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * fix: change REDIS_POOL_ON_EMPTY_BEHAVIOR default to WAIT The default value 'CREATE' is not supported in radix v4 and causes integration tests to panic at startup. Changed default to 'WAIT' which matches radix v4's actual pool behavior (always blocks when empty). This fixes integration test failures where tests without explicit REDIS_POOL_ON_EMPTY_BEHAVIOR settings would panic during initialization with: "REDIS_POOL_ON_EMPTY_BEHAVIOR=CREATE is not supported in radix v4" Also updated documentation to clarify that CREATE/ERROR are not supported and marked RedisPoolOnEmptyWaitDuration as deprecated. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * test: fix cluster connection timeout and context bug - Fix WaitForTcpPort to use timeoutCtx instead of ctx This ensures the timeout parameter is actually respected when dialing TCP connections. - Increase gRPC server startup timeout from 1s to 10s Radix v4 cluster connection initialization takes longer, especially when establishing connections to multiple cluster nodes. This prevents "connection refused" errors in integration tests. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: extract dialer creation logic to reduce duplication Consolidates Redis and Sentinel dialer setup into a reusable createDialer helper function, eliminating ~30 lines of duplicated code. Improves logging by including connection target details (e.g., "sentinel(master,host1,host2)") instead of generic "sentinel" string. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: remove deprecated REDIS_POOL_ON_EMPTY_WAIT_DURATION settings Remove the deprecated poolOnEmptyWaitDuration parameter and related configuration settings as they have no effect in radix v4. The pool always blocks until a connection is available when using WAIT behavior. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * refactor: auto-select pipeline mode based on Redis type Remove REDIS_USE_EXPLICIT_PIPELINE configuration option and automatically determine pipeline mode based on Redis deployment type: - Cluster mode: uses grouped pipeline (groups same-key commands) - INCRBY + EXPIRE for same key are pipelined together (same slot) - Reduces round-trips from 2 to 1 per key in cluster mode - Single/Sentinel mode: uses explicit pipeline (batches all commands) - All commands in one pipeline for minimal latency - Optimal for non-cluster deployments This simplifies configuration by removing user-facing options while automatically choosing the optimal pipeline strategy for each Redis type. Breaking changes: - Remove REDIS_USE_EXPLICIT_PIPELINE env var - Remove REDIS_PERSECOND_USE_EXPLICIT_PIPELINE env var - Remove UseExplicitPipeline() interface method Signed-off-by: seonghyun <seonghyunoh@gmail.com> * docs: remove non-existent REDIS_USE_EXPLICIT_PIPELINE from README The REDIS_USE_EXPLICIT_PIPELINE and REDIS_PERSECOND_USE_EXPLICIT_PIPELINE settings were documented in README but do not exist in settings.go. Removed the documentation to match the actual implementation. Signed-off-by: seonghyun <seonghyunoh@gmail.com> * style: fix gofmt formatting in settings.go Signed-off-by: seonghyun <seonghyunoh@gmail.com> --------- Signed-off-by: seonghyun <seonghyunoh@gmail.com> add support for response dynamic metadata (#1027) * add support for response dynamic metadata Signed-off-by: zirain <zirain2009@gmail.com> * address Colin's comment Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> fix: apply TLS and auth config to Redis Sentinel connections (#1015) * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> * fix: apply TLS and auth config to Redis Sentinel connections When using Redis Sentinel with TLS enabled, the client was failing to connect to Sentinel nodes because the TLS configuration was not being applied to the SentinelConnFunc. This caused "SSL wrong version number" errors and connection resets. This fix adds a sentinelDialFunc that properly applies: - TLS configuration (when REDIS_TLS=true) - Authentication settings (when REDIS_AUTH is set) - Connection timeout settings The fix mirrors the approach used for the main Redis connection dial function, ensuring consistent configuration across both Sentinel and data node connections. Fixes connection to Redis Sentinel over TLS. Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> --------- Signed-off-by: Stefan Kolesnikowicz <stefan@sandnetworks.com> Signed-off-by: stekole <stefan@sandnetworks.com> feat: Add Pool On-Empty Behavior Configuration for Redis Connections (#1018) * feat: Add Pool On-Empty Behavior Configuration for Redis Connections Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> * update Signed-off-by: notdu <huudutg@gmail.com> --------- Signed-off-by: notdu <huudutg@gmail.com> [ISSUE] Fix: Wildcard Stats Key Behavior Changes (#1017) * Fix: Preserve metrics for wild card Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Unify matchedWildCardKey for if-else statement Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove hasShareThreshold conditional check in non-wild-card block Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Prevent log debug to creating stats from executing twice per request Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove redundant assignment Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Fix: Remove dead code Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Refactor: unify logic to include value to stats Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> (fixes): local cache stat test fixes (#1013) * (fixes): local cache stat test fixes Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> * (fixes): invoke TestOverLimitWithStopCacheKeyIncrementWhenOverlimitConfig local cache stat tests Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> --------- Signed-off-by: Sagar Waidande <sagar10018233@gmail.com> [Proposal] Share Threshold for Wildcard Rate Limiting (#1016) * Add share_threshold to make wild card values can share rate limit threshold Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Implement lazy initilization based on reviews Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: Nam Dang <xuannam230201@gmail.com> feat: Add field to add unspecified value to metric (#996) * Add field to add unspecified value to metric Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update README.md to pass docs_check_format check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update format to pass pre-commit check Signed-off-by: Nam Dang <xuannam230201@gmail.com> * Update based on comments and add more unit tests Signed-off-by: Nam Dang <xuannam230201@gmail.com> --------- Signed-off-by: xuannam230201 <xuannam230201@gmail.com> Signed-off-by: Nam Dang <xuannam230201@gmail.com> Replace Alpine with Google's distroless static image for enhanced sec… (#993) * Replace Alpine with Google's distroless static image for enhanced security and simplified maintenance. Includes CA certificates automatically and provides debug variant for troubleshooting. * security: pin distroless image to SHA and use nonroot variant - Pin gcr.io/distroless/static-debian12:nonroot to specific SHA digest - Ensures deterministic builds and prevents supply chain attacks - Use nonroot variant for enhanced security (runs as UID 65532) - Follows same pattern as Envoy proxy for consistency - Update documentation to reflect security improvements feat: add connection timeout configuration for Redis operations (#987) Signed-off-by: notdu <huudutg@gmail.com> build(deps): bump google.golang.org/protobuf from 1.36.7 to 1.36.10 (#980) Bumps google.golang.org/protobuf from 1.36.7 to 1.36.10. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang in /examples/xds-sotw-config-server (#981) Bumps golang from 1.24.5 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump golang from 1.24.6 to 1.25.3 (#983) Bumps golang from 1.24.6 to 1.25.3. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#976) Bumps alpine from `1e42bbe` to `4b7ce07`. --- updated-dependencies: - dependency-name: alpine dependency-version: 4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT (#1206) * Add calendar-aligned MONTH rate limit, gated by USE_CALENDAR_MONTH_RATE_LIMIT A unit: month rate limit is computed as a fixed 60*60*24*30 second window counted from the Unix epoch, so it neither aligns with real calendar months nor accounts for months of different lengths (RDGRS-1999). Add a USE_CALENDAR_MONTH_RATE_LIMIT setting (default false) that, when enabled, buckets MONTH cache keys by UTC calendar month, sets their TTL/expiration to the actual time remaining until month end, and reports that same value as the reset duration. Defaults to false so existing MONTH limits keep their current reset behavior unless explicitly opted in. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * Trigger CI Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * docs: regenerate README TOC for new calendar-month section Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * memcached: fix expiration >30 days being misread as a Unix timestamp Memcached treats any expiration value greater than 30 days as an absolute Unix timestamp rather than a relative TTL. Calendar-aligned MONTH limits can produce a relative expiration up to 2,678,400 seconds (31-day months), which was passed straight into memcache.Item.Expiration and caused those keys to be treated as already expired. Convert the expiration to an absolute Unix timestamp whenever it would exceed memcached's 30-day relative-TTL threshold. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * test: fix call sites left out of sync by main merge The merge of main (is_negative_hits, []uint64 -> []utils.HitsAddend) into calendar-month-rate-limit (added useCalendarMonth bool param) left several test call sites using the pre-merge signatures for NewBaseRateLimit, NewRateLimitCacheImpl, and NewFixedRateLimitCacheImpl. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Signed-off-by: Kiran Malsetty <93211513+OS-kiranmalsetty@users.noreply.github.com> feat: implement is_negative_hits in rate limit descriptor (#1140) * feat: implement is_negative_hits in rate limit descriptor Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> * added details to readme Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> --------- Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com> redis: log recovery when a connection succeeds after a prior dial error (#1205) Operators currently only see repeated dial-error logs and have no explicit signal when the pool starts succeeding again. Track whether the last dial attempt failed and log once when a subsequent connection succeeds. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> Update Go references and vulnerable dependencies (#1204) * Update Go references to 1.26.5 Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> * Update vulnerable Go dependencies Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> --------- Signed-off-by: Phellippe Lima <phellippe.end@gmail.com> deps: bump x/net, x/text, x/sys to fix remaining CVEs (#1196) Follow-up to #1154 (which bumped x/net to 0.55.0). Bumps the golang.org/x dependencies to their latest patched releases to remediate the CVEs still outstanding after #1154: - golang.org/x/net v0.55.0 -> v0.57.0 (CVE-2026-46600, fixed in 0.56.0) - golang.org/x/text v0.37.0 -> v0.40.0 (CVE-2026-56852, fixed in 0.39.0) - golang.org/x/sys v0.45.0 -> v0.47.0 (already patched; kept current) No source changes required; `go build ./...` passes. Signed-off-by: Yitong Feng <yife@microsoft.com> redis: optionally close pooled connections on READONLY error replies (#1191) * redis: optionally close pooled connections on READONLY error replies After a master->replica failover in deployments that fail over by repointing an address at the new master (a Kubernetes Service, DNS, or a proxy - e.g. Redis without Sentinel, Dragonfly, KeyDB), the demoted master keeps already-established connections open. radix only discards pooled connections on IO errors, so those stale connections are reused forever and every write on them keeps failing with READONLY until the process restarts, turning a routine failover into a permanent rate limiting outage. Add an opt-in setting, REDIS_CLOSE_CONNECTION_ON_READONLY_ERROR (default false), that wraps pooled connections so a READONLY error reply strips radix's resp.ErrConnUsable wrapper. The pool then discards the connection and re-dials through the configured address, reaching the current master. The failing command still returns its error to the caller; only the connection handling changes. Applies to the main and per-second clients across single, cluster, and sentinel modes. Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> * fix README.md Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> --------- Signed-off-by: kiran malsetty <kiran.malsetty@outsystems.com> build(deps): bump docker/setup-qemu-action from 3.2.0 to 4.2.0 (#1179) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 4.2.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...96fe6ef7f33517b61c61be40b68a1882f3264fb8) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump actions/checkout from 4.1.7 to 7.0.0 (#1173) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 7.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> build(deps): bump alpine in /integration-test (#1172) Bumps alpine from `4b7ce07` to `28bd5fe`. --- updated-dependencies: - dependency-name: alpine dependency-version: 28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add metadata to rate limit descriptors pb to yaml (#1175) Signed-off-by: achoo30 <achoo30@bloomberg.net> update proto to support metadata (#1174) Signed-off-by: achoo30 <achoo30@bloomberg.net> Update to golang-1.26.4 and update golang.org/x/net to 0.55.0 (#1154) Signed-off-by: Fred Dafunk <bloomenergyguy@gmail.com> Co-authored-by: collin-lee <collin.lee@salesforce.com> feat: bound cluster pipeline parallelism (#1149) * redis: bound cluster pipeline parallelism Signed-off-by: dthuynh <dthuynh@axon.com> * Refactor to address comment: use gRPC request context in PipeDo, cap the parallelism to RedisPoolSize Signed-off-by: dthuynh <dthuynh@axon.com> --------- Signed-off-by: dthuynh <dthuynh@axon.com> Co-authored-by: dthuynh <dthuynh@axon.com> fix: correct typos in memcache error messages and variable name (#1150) Signed-off-by: Immanuel Tikhonov <pchpr.00@list.ru> Signed-off-by: immanuwell <pchpr.00@list.ru> Update to golang 1.26.3 (#1152) Co-authored-by: collin-lee <collin.lee@salesforce.com> Add quota mode to rate limit descriptor proto (#1148) feat: add retry in init phase instead of panic directly (#1144) * feat: add retry in init phase instead of panic directly Signed-off-by: zirain <zirain2009@gmail.com> * respect signal handling for graceful shutdown Signed-off-by: zirain <zirain2009@gmail.com> * fix test Signed-off-by: zirain <zirain2009@gmail.com> --------- Signed-off-by: zirain <zirain2009@gmail.com> Add integration test for quota based service selection. (#1114) Signed-off-by: Yan Avlasov <yavlasov@google.com> build: pin golang:1.26.2 to multi-arch index digest (#1131) PR #1124 updated the golang base image from 1.26.1 to 1.26.2, but the new digest sha256:7095ad02810845fa35d1fb090b8e57dd20dce4ca36b29b42951 802350d2ec90e is a single-arch (linux/amd64) image manifest rather than a multi-arch index. The previous 1.26.1 digest sha256:e2ddb153f7 86ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 is an OCI image index covering linux/amd64, arm64/v8, arm/v7, 386, ppc64le, riscv64, s390x and windows/amd64. When buildx is asked to produce a non-amd64 variant of the published envoyproxy/ratelimit image, the FROM line resolves to the amd64 base on every platform, so the resulting binary is amd64 regardless of the target. The multi-arch publish then stamps that amd64 binary into the arm64 layer of the released index, producing an image that fails on arm64 nodes with: exec /bin/ratelimit: exec format error Swap to t…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps actions/checkout from 4.1.7 to 7.0.0.
Release notes
Sourced from actions/checkout's releases.
... (truncated)
Changelog
Sourced from actions/checkout's changelog.
... (truncated)
Commits
9c091bbupdate error wording (#2467)1044a6dgetting ready for checkout v7 release (#2464)f028218Bump the minor-npm-dependencies group across 1 directory with 3 updates (#2462)d914b26upgrade module to esm and update dependencies (#2463)537c7efBump@actions/coreand@actions/tool-cacheand Remove uuid (#2459)130a169Bump js-yaml from 4.1.0 to 4.2.0 (#2461)7d09575Bump flatted from 3.3.1 to 3.4.2 (#2460)0f9f3aaBump actions/publish-immutable-action (#2458)f9e715ablock checking out fork pr for pull_request_target and workflow_run (#2454)df4cb1cUpdate changelog for v6.0.3 (#2446)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)