This release adds support for Redis 8.8. The README's supported-versions list now includes Redis 8.8 alongside 8.0/8.2/8.4, and CI exercises the 8.8 client-libs-test image across the full suite (Makefile, build workflow, doctests, run-tests action, and docker-compose).
Coverage for the new commands that ship in the 8.x line, rounded out in this release:
AR* array data type (#3813) — new array data structure, exposed via the ArrayCmdable interface (see the experimental-features highlight below).
INCREX (#3816) — atomic increment with expiration in a single round-trip.
XNACK (#3790) — explicit negative-acknowledge of pending stream entries.
XAUTOCLAIM PEL deletes (#3798) — XAUTOCLAIM/XAUTOCLAIMJUSTID now return the list of deleted message IDs from the pending entries list.
TS.RANGE multiple aggregators (#3791) — TS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGE accept multiple aggregators in a single call.
Z(UNION|INTER|DIFF)COUNT aggregator (#3802) — COUNT reducer for sorted-set set operations.
JSON.SET FPHA (#3797) — new FPHA argument that specifies the floating-point type for homogeneous FP arrays.
Stable RESP3 for RediSearch (UnstableResp3 deprecated)
FT.SEARCH, FT.AGGREGATE, FT.INFO, FT.SPELLCHECK, and FT.SYNDUMP now parse RESP3 (map) responses into the same typed result objects as RESP2 — Val() and Result() work uniformly on both protocols, no flag required. Previously, RESP3 search responses required UnstableResp3: true and were returned as opaque maps accessible only via RawResult() / RawVal().
As a result, the UnstableResp3 option is now a no-op across every options struct (Options, ClusterOptions, UniversalOptions, FailoverOptions, RingOptions) and has been marked // Deprecated:. The field is retained for backwards compatibility — existing code that sets UnstableResp3: true will continue to compile and behave identically — but it will be removed in a future release and new code should not set it. RawResult() / RawVal() continue to work for callers that prefer the raw RESP payload.
Adds an experimental ArrayCmdable interface with the AR* command family (ARSet, ARGet, ARGetRange, ARMSet, ARMGet, ARDel, ARDelRange, ARScan, ARSeek, ARNext, ARLastItems, ARGrep, ARGrepWithValues, ARInfo/ARInfoFull, and typed reducers AROpSum/AROpMin/AROpMax/AROpAnd/AROpOr/AROpXor/AROpMatch/AROpUsed) for working with Redis 8.8's new array data type. API is experimental and may change in a future release.
RESP3 search parser: First-class RESP3 parsing for FT.SEARCH/FT.AGGREGATE/FT.INFO/FT.SPELLCHECK/FT.SYNDUMP responses with backwards compatibility for RESP2 (#3741) by @ndyakov
INCREX: New INCREX command support — atomic increment with expiration (#3816) by @ndyakov
XNACK: Client support for the XNACK stream command for explicitly negative-acknowledging pending entries (#3790) by @elena-kolevska
TS range multiple aggregators: TS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGE now accept multiple aggregators in a single call (#3791) by @elena-kolevska
XAutoClaim deleted IDs: XAUTOCLAIM/XAUTOCLAIMJUSTID now return the list of deleted message IDs from the PEL (#3798) by @Khukharr
JSON.SET FPHA: JSON.SET accepts a new FPHA argument that specifies the floating-point type for homogeneous floating-point arrays (#3797) by @ndyakov
Sorted-set union/intersection COUNT: ZUNION/ZINTER/ZDIFF aggregator now supports COUNT (#3802) by @ofekshenawa
FT.HYBRID vector validation: Validates hybrid-search vector input types and adds proper typed vector parameters (#3756) by @DengY11
Cluster pool wait stats: ClusterClient.PoolStats() now accumulates WaitCount and WaitDurationNs across all node pools (previously always zero) (#3809) by @LINKIWI
🐛 Bug Fixes
TLS-only Cluster PubSub: CLUSTER SLOTS port-0 entries now fall back to the origin endpoint's port, fixing dial tcp <ip>:0: connection refused on TLS-only clusters started with --port 0 --tls-port <port> (fixes #3726) (#3828) by @ndyakov
Sharded PubSub reconnect routing: PubSub.conn() now passes both regular (c.channels) and sharded (c.schannels) channels into the per-PubSub newConn closure. Previously, ClusterClient.SSubscribe-only PubSubs reconnected to a random node (because the routing closure saw an empty channel list), the SSUBSCRIBE was sent to the wrong shard, and the resulting MOVED reply was silently dropped (#3829) by @ndyakov
ClusterClient Watch retry: User errors returned from a Watch callback are no longer subjected to cluster-retry classification; transient cluster errors still retry, but a callback returning e.g. net.ErrClosed short-circuits immediately (#3821) by @obiyang
Sentinel concurrent-probe leak: MasterAddr's concurrent sentinel probe now closes the non-winning sentinel clients instead of leaking them (#3827) by @cxljs
Sentinel rediscovery loop on master-only setups: replicaAddrs no longer tears down the cached sentinel client when the replica list is empty, eliminating a continuous rediscovery loop on master-only Sentinel deployments that flooded logs and added per-operation latency (#3795) by @shahyash2609
Pool CloseConn hooks: Pool.CloseConn now triggers registered hooks, fixing a memory leak when connections are closed explicitly rather than via the normal removal path (#3818) by @ndyakov
Dial TCP error redirection: Wrapped dial tcp errors are now correctly classified as redirectable so cluster routing can recover from a single unreachable node (#3810) by @vladisa88
Pool Close health checks: ConnPool.Close now only runs health checks against idle connections, avoiding spurious activity on connections still in use (#3805) by @ndyakov
VLinks return type: Fixed the return type of VLINKS/VLINKSWITHSCORES vector-set replies (#3820) by @romanpovol
🧪 Testing & Infrastructure
Flaky tests: Stabilized several flaky tests in the sentinel and pool suites (#3815) by @ndyakov
Sentinel failover metric race: Fixed a data race in the sentinel failover metric test (#3824) by @cxljs
waitForSentinelClusterStable post-conditions: The sentinel test harness now waits for replicas to be fully connected (not just present in the count) and is robust to randomized spec ordering after failover specs, eliminating an intermittent Expected master to equal slave flake (#3830) by @ndyakov
govulncheck workflow: New scheduled GitHub Actions workflow runs govulncheck on every push, PR, and weekly, surfacing newly disclosed Go vulnerabilities even when no code changes (#3779) by @solardome
CI Redis 8.8-rc1: CI now exercises the 8.8-rc1 Redis image (#3814) by @ofekshenawa
🧰 Maintenance
Cmd.Slot() lookup refactor: Caches the per-command CommandInfo and short-circuits keyless commands before the switch dispatch, removing redundant Peek calls (#3804) by @retr0-kernel
stdlib math/rand: Replaced internal/rand with math/rand from the standard library now that the minimum Go version is 1.24 (#3823) by @cxljs
ConnPool queue channel: Removed the unused queue channel from ConnPool, trimming the pool's footprint (#3826) by @cxljs
Extra packages LICENSE: Added a LICENSE file to each extra/* package (#3817) by @ndyakov
README & CI image: Documentation refresh and bumped the default CI image tag (#3822) by @ndyakov
👥 Contributors
We'd like to thank all the contributors who worked on this release!
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) | `v9.19.0` → `v9.20.0` |  |  |
---
### Release Notes
<details>
<summary>redis/go-redis (github.com/redis/go-redis/v9)</summary>
### [`v9.20.0`](https://github.com/redis/go-redis/releases/tag/v9.20.0): 9.20.0
[Compare Source](https://github.com/redis/go-redis/compare/v9.19.0...v9.20.0)
#### 🚀 Highlights
##### Redis 8.8 Support
This release adds support for **Redis 8.8**. The README's supported-versions list now includes Redis 8.8 alongside 8.0/8.2/8.4, and CI exercises the `8.8` client-libs-test image across the full suite (Makefile, build workflow, doctests, run-tests action, and docker-compose).
Coverage for the new commands that ship in the 8.x line, rounded out in this release:
- **`AR*` array data type** ([#​3813](https://github.com/redis/go-redis/pull/3813)) — new array data structure, exposed via the `ArrayCmdable` interface (see the experimental-features highlight below).
- **`INCREX`** ([#​3816](https://github.com/redis/go-redis/pull/3816)) — atomic increment with expiration in a single round-trip.
- **`XNACK`** ([#​3790](https://github.com/redis/go-redis/pull/3790)) — explicit negative-acknowledge of pending stream entries.
- **`XAUTOCLAIM` PEL deletes** ([#​3798](https://github.com/redis/go-redis/pull/3798)) — `XAUTOCLAIM`/`XAUTOCLAIMJUSTID` now return the list of deleted message IDs from the pending entries list.
- **`TS.RANGE` multiple aggregators** ([#​3791](https://github.com/redis/go-redis/pull/3791)) — `TS.RANGE`/`TS.REVRANGE`/`TS.MRANGE`/`TS.MREVRANGE` accept multiple aggregators in a single call.
- **`Z(UNION|INTER|DIFF)` `COUNT` aggregator** ([#​3802](https://github.com/redis/go-redis/pull/3802)) — `COUNT` reducer for sorted-set set operations.
- **`JSON.SET FPHA`** ([#​3797](https://github.com/redis/go-redis/pull/3797)) — new `FPHA` argument that specifies the floating-point type for homogeneous FP arrays.
CI image bump ([#​3814](https://github.com/redis/go-redis/pull/3814)) by [@​ofekshenawa](https://github.com/ofekshenawa). Command coverage contributions by [@​cxljs](https://github.com/cxljs), [@​elena-kolevska](https://github.com/elena-kolevska), [@​Khukharr](https://github.com/Khukharr), [@​ndyakov](https://github.com/ndyakov), and [@​ofekshenawa](https://github.com/ofekshenawa).
##### Stable RESP3 for RediSearch (`UnstableResp3` deprecated)
`FT.SEARCH`, `FT.AGGREGATE`, `FT.INFO`, `FT.SPELLCHECK`, and `FT.SYNDUMP` now parse RESP3 (map) responses into the same typed result objects as RESP2 — `Val()` and `Result()` work uniformly on both protocols, no flag required. Previously, RESP3 search responses required `UnstableResp3: true` and were returned as opaque maps accessible only via `RawResult()` / `RawVal()`.
As a result, the `UnstableResp3` option is now a **no-op** across every options struct (`Options`, `ClusterOptions`, `UniversalOptions`, `FailoverOptions`, `RingOptions`) and has been marked `// Deprecated:`. The field is retained for backwards compatibility — existing code that sets `UnstableResp3: true` will continue to compile and behave identically — but it will be removed in a future release and new code should not set it. `RawResult()` / `RawVal()` continue to work for callers that prefer the raw RESP payload.
([#​3741](https://github.com/redis/go-redis/pull/3741)) by [@​ndyakov](https://github.com/ndyakov)
##### Experimental Array Data Structure Commands
Adds an experimental `ArrayCmdable` interface with the `AR*` command family (`ARSet`, `ARGet`, `ARGetRange`, `ARMSet`, `ARMGet`, `ARDel`, `ARDelRange`, `ARScan`, `ARSeek`, `ARNext`, `ARLastItems`, `ARGrep`, `ARGrepWithValues`, `ARInfo`/`ARInfoFull`, and typed reducers `AROpSum`/`AROpMin`/`AROpMax`/`AROpAnd`/`AROpOr`/`AROpXor`/`AROpMatch`/`AROpUsed`) for working with Redis 8.8's new array data type. **API is experimental and may change in a future release.**
([#​3813](https://github.com/redis/go-redis/pull/3813)) by [@​cxljs](https://github.com/cxljs)
#### ✨ New Features
- **RESP3 search parser**: First-class RESP3 parsing for `FT.SEARCH`/`FT.AGGREGATE`/`FT.INFO`/`FT.SPELLCHECK`/`FT.SYNDUMP` responses with backwards compatibility for RESP2 ([#​3741](https://github.com/redis/go-redis/pull/3741)) by [@​ndyakov](https://github.com/ndyakov)
- **INCREX**: New `INCREX` command support — atomic increment with expiration ([#​3816](https://github.com/redis/go-redis/pull/3816)) by [@​ndyakov](https://github.com/ndyakov)
- **XNACK**: Client support for the `XNACK` stream command for explicitly negative-acknowledging pending entries ([#​3790](https://github.com/redis/go-redis/pull/3790)) by [@​elena-kolevska](https://github.com/elena-kolevska)
- **TS range multiple aggregators**: `TS.RANGE`/`TS.REVRANGE`/`TS.MRANGE`/`TS.MREVRANGE` now accept multiple aggregators in a single call ([#​3791](https://github.com/redis/go-redis/pull/3791)) by [@​elena-kolevska](https://github.com/elena-kolevska)
- **`XAutoClaim` deleted IDs**: `XAUTOCLAIM`/`XAUTOCLAIMJUSTID` now return the list of deleted message IDs from the PEL ([#​3798](https://github.com/redis/go-redis/pull/3798)) by [@​Khukharr](https://github.com/Khukharr)
- **`JSON.SET FPHA`**: `JSON.SET` accepts a new `FPHA` argument that specifies the floating-point type for homogeneous floating-point arrays ([#​3797](https://github.com/redis/go-redis/pull/3797)) by [@​ndyakov](https://github.com/ndyakov)
- **Sorted-set union/intersection COUNT**: `ZUNION`/`ZINTER`/`ZDIFF` aggregator now supports `COUNT` ([#​3802](https://github.com/redis/go-redis/pull/3802)) by [@​ofekshenawa](https://github.com/ofekshenawa)
- **`FT.HYBRID` vector validation**: Validates hybrid-search vector input types and adds proper typed vector parameters ([#​3756](https://github.com/redis/go-redis/pull/3756)) by [@​DengY11](https://github.com/DengY11)
- **Cluster pool wait stats**: `ClusterClient.PoolStats()` now accumulates `WaitCount` and `WaitDurationNs` across all node pools (previously always zero) ([#​3809](https://github.com/redis/go-redis/pull/3809)) by [@​LINKIWI](https://github.com/LINKIWI)
#### 🐛 Bug Fixes
- **TLS-only Cluster PubSub**: `CLUSTER SLOTS` port-0 entries now fall back to the origin endpoint's port, fixing `dial tcp <ip>:0: connection refused` on TLS-only clusters started with `--port 0 --tls-port <port>` (fixes [#​3726](https://github.com/redis/go-redis/issues/3726)) ([#​3828](https://github.com/redis/go-redis/pull/3828)) by [@​ndyakov](https://github.com/ndyakov)
- **Sharded PubSub reconnect routing**: `PubSub.conn()` now passes both regular (`c.channels`) and sharded (`c.schannels`) channels into the per-PubSub `newConn` closure. Previously, `ClusterClient.SSubscribe`-only PubSubs reconnected to a random node (because the routing closure saw an empty channel list), the `SSUBSCRIBE` was sent to the wrong shard, and the resulting `MOVED` reply was silently dropped ([#​3829](https://github.com/redis/go-redis/pull/3829)) by [@​ndyakov](https://github.com/ndyakov)
- **ClusterClient `Watch` retry**: User errors returned from a `Watch` callback are no longer subjected to cluster-retry classification; transient cluster errors still retry, but a callback returning e.g. `net.ErrClosed` short-circuits immediately ([#​3821](https://github.com/redis/go-redis/pull/3821)) by [@​obiyang](https://github.com/obiyang)
- **Sentinel concurrent-probe leak**: `MasterAddr`'s concurrent sentinel probe now closes the non-winning sentinel clients instead of leaking them ([#​3827](https://github.com/redis/go-redis/pull/3827)) by [@​cxljs](https://github.com/cxljs)
- **Sentinel rediscovery loop on master-only setups**: `replicaAddrs` no longer tears down the cached sentinel client when the replica list is empty, eliminating a continuous rediscovery loop on master-only Sentinel deployments that flooded logs and added per-operation latency ([#​3795](https://github.com/redis/go-redis/pull/3795)) by [@​shahyash2609](https://github.com/shahyash2609)
- **Pool `CloseConn` hooks**: `Pool.CloseConn` now triggers registered hooks, fixing a memory leak when connections are closed explicitly rather than via the normal removal path ([#​3818](https://github.com/redis/go-redis/pull/3818)) by [@​ndyakov](https://github.com/ndyakov)
- **Dial TCP error redirection**: Wrapped `dial tcp` errors are now correctly classified as redirectable so cluster routing can recover from a single unreachable node ([#​3810](https://github.com/redis/go-redis/pull/3810)) by [@​vladisa88](https://github.com/vladisa88)
- **Pool `Close` health checks**: `ConnPool.Close` now only runs health checks against idle connections, avoiding spurious activity on connections still in use ([#​3805](https://github.com/redis/go-redis/pull/3805)) by [@​ndyakov](https://github.com/ndyakov)
- **VLinks return type**: Fixed the return type of `VLINKS`/`VLINKSWITHSCORES` vector-set replies ([#​3820](https://github.com/redis/go-redis/pull/3820)) by [@​romanpovol](https://github.com/romanpovol)
#### 🧪 Testing & Infrastructure
- **Flaky tests**: Stabilized several flaky tests in the sentinel and pool suites ([#​3815](https://github.com/redis/go-redis/pull/3815)) by [@​ndyakov](https://github.com/ndyakov)
- **Sentinel failover metric race**: Fixed a data race in the sentinel failover metric test ([#​3824](https://github.com/redis/go-redis/pull/3824)) by [@​cxljs](https://github.com/cxljs)
- **`waitForSentinelClusterStable` post-conditions**: The sentinel test harness now waits for replicas to be fully connected (not just present in the count) and is robust to randomized spec ordering after failover specs, eliminating an intermittent `Expected master to equal slave` flake ([#​3830](https://github.com/redis/go-redis/pull/3830)) by [@​ndyakov](https://github.com/ndyakov)
- **`govulncheck` workflow**: New scheduled GitHub Actions workflow runs `govulncheck` on every push, PR, and weekly, surfacing newly disclosed Go vulnerabilities even when no code changes ([#​3779](https://github.com/redis/go-redis/pull/3779)) by [@​solardome](https://github.com/solardome)
- **CI Redis 8.8-rc1**: CI now exercises the 8.8-rc1 Redis image ([#​3814](https://github.com/redis/go-redis/pull/3814)) by [@​ofekshenawa](https://github.com/ofekshenawa)
#### 🧰 Maintenance
- **`Cmd.Slot()` lookup refactor**: Caches the per-command `CommandInfo` and short-circuits keyless commands before the switch dispatch, removing redundant `Peek` calls ([#​3804](https://github.com/redis/go-redis/pull/3804)) by [@​retr0-kernel](https://github.com/retr0-kernel)
- **stdlib `math/rand`**: Replaced `internal/rand` with `math/rand` from the standard library now that the minimum Go version is 1.24 ([#​3823](https://github.com/redis/go-redis/pull/3823)) by [@​cxljs](https://github.com/cxljs)
- **ConnPool queue channel**: Removed the unused queue channel from `ConnPool`, trimming the pool's footprint ([#​3826](https://github.com/redis/go-redis/pull/3826)) by [@​cxljs](https://github.com/cxljs)
- **Extra packages LICENSE**: Added a LICENSE file to each `extra/*` package ([#​3817](https://github.com/redis/go-redis/pull/3817)) by [@​ndyakov](https://github.com/ndyakov)
- **README & CI image**: Documentation refresh and bumped the default CI image tag ([#​3822](https://github.com/redis/go-redis/pull/3822)) by [@​ndyakov](https://github.com/ndyakov)
#### 👥 Contributors
We'd like to thank all the contributors who worked on this release!
[@​cxljs](https://github.com/cxljs), [@​DengY11](https://github.com/DengY11), [@​elena-kolevska](https://github.com/elena-kolevska), [@​Khukharr](https://github.com/Khukharr), [@​LINKIWI](https://github.com/LINKIWI), [@​ndyakov](https://github.com/ndyakov), [@​obiyang](https://github.com/obiyang), [@​ofekshenawa](https://github.com/ofekshenawa), [@​retr0-kernel](https://github.com/retr0-kernel), [@​romanpovol](https://github.com/romanpovol), [@​shahyash2609](https://github.com/shahyash2609), [@​solardome](https://github.com/solardome), [@​vladisa88](https://github.com/vladisa88)
***
**Full Changelog**: <https://github.com/redis/go-redis/compare/v9.19.0...v9.20.0>
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuOCIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
This PR contains the following updates:
v9.19.0→v9.20.0Release Notes
redis/go-redis (github.com/redis/go-redis/v9)
v9.20.0: 9.20.0Compare Source
🚀 Highlights
Redis 8.8 Support
This release adds support for Redis 8.8. The README's supported-versions list now includes Redis 8.8 alongside 8.0/8.2/8.4, and CI exercises the
8.8client-libs-test image across the full suite (Makefile, build workflow, doctests, run-tests action, and docker-compose).Coverage for the new commands that ship in the 8.x line, rounded out in this release:
AR*array data type (#3813) — new array data structure, exposed via theArrayCmdableinterface (see the experimental-features highlight below).INCREX(#3816) — atomic increment with expiration in a single round-trip.XNACK(#3790) — explicit negative-acknowledge of pending stream entries.XAUTOCLAIMPEL deletes (#3798) —XAUTOCLAIM/XAUTOCLAIMJUSTIDnow return the list of deleted message IDs from the pending entries list.TS.RANGEmultiple aggregators (#3791) —TS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGEaccept multiple aggregators in a single call.Z(UNION|INTER|DIFF)COUNTaggregator (#3802) —COUNTreducer for sorted-set set operations.JSON.SET FPHA(#3797) — newFPHAargument that specifies the floating-point type for homogeneous FP arrays.CI image bump (#3814) by @ofekshenawa. Command coverage contributions by @cxljs, @elena-kolevska, @Khukharr, @ndyakov, and @ofekshenawa.
Stable RESP3 for RediSearch (
UnstableResp3deprecated)FT.SEARCH,FT.AGGREGATE,FT.INFO,FT.SPELLCHECK, andFT.SYNDUMPnow parse RESP3 (map) responses into the same typed result objects as RESP2 —Val()andResult()work uniformly on both protocols, no flag required. Previously, RESP3 search responses requiredUnstableResp3: trueand were returned as opaque maps accessible only viaRawResult()/RawVal().As a result, the
UnstableResp3option is now a no-op across every options struct (Options,ClusterOptions,UniversalOptions,FailoverOptions,RingOptions) and has been marked// Deprecated:. The field is retained for backwards compatibility — existing code that setsUnstableResp3: truewill continue to compile and behave identically — but it will be removed in a future release and new code should not set it.RawResult()/RawVal()continue to work for callers that prefer the raw RESP payload.(#3741) by @ndyakov
Experimental Array Data Structure Commands
Adds an experimental
ArrayCmdableinterface with theAR*command family (ARSet,ARGet,ARGetRange,ARMSet,ARMGet,ARDel,ARDelRange,ARScan,ARSeek,ARNext,ARLastItems,ARGrep,ARGrepWithValues,ARInfo/ARInfoFull, and typed reducersAROpSum/AROpMin/AROpMax/AROpAnd/AROpOr/AROpXor/AROpMatch/AROpUsed) for working with Redis 8.8's new array data type. API is experimental and may change in a future release.(#3813) by @cxljs
✨ New Features
FT.SEARCH/FT.AGGREGATE/FT.INFO/FT.SPELLCHECK/FT.SYNDUMPresponses with backwards compatibility for RESP2 (#3741) by @ndyakovINCREXcommand support — atomic increment with expiration (#3816) by @ndyakovXNACKstream command for explicitly negative-acknowledging pending entries (#3790) by @elena-kolevskaTS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGEnow accept multiple aggregators in a single call (#3791) by @elena-kolevskaXAutoClaimdeleted IDs:XAUTOCLAIM/XAUTOCLAIMJUSTIDnow return the list of deleted message IDs from the PEL (#3798) by @KhukharrJSON.SET FPHA:JSON.SETaccepts a newFPHAargument that specifies the floating-point type for homogeneous floating-point arrays (#3797) by @ndyakovZUNION/ZINTER/ZDIFFaggregator now supportsCOUNT(#3802) by @ofekshenawaFT.HYBRIDvector validation: Validates hybrid-search vector input types and adds proper typed vector parameters (#3756) by @DengY11ClusterClient.PoolStats()now accumulatesWaitCountandWaitDurationNsacross all node pools (previously always zero) (#3809) by @LINKIWI🐛 Bug Fixes
CLUSTER SLOTSport-0 entries now fall back to the origin endpoint's port, fixingdial tcp <ip>:0: connection refusedon TLS-only clusters started with--port 0 --tls-port <port>(fixes #3726) (#3828) by @ndyakovPubSub.conn()now passes both regular (c.channels) and sharded (c.schannels) channels into the per-PubSubnewConnclosure. Previously,ClusterClient.SSubscribe-only PubSubs reconnected to a random node (because the routing closure saw an empty channel list), theSSUBSCRIBEwas sent to the wrong shard, and the resultingMOVEDreply was silently dropped (#3829) by @ndyakovWatchretry: User errors returned from aWatchcallback are no longer subjected to cluster-retry classification; transient cluster errors still retry, but a callback returning e.g.net.ErrClosedshort-circuits immediately (#3821) by @obiyangMasterAddr's concurrent sentinel probe now closes the non-winning sentinel clients instead of leaking them (#3827) by @cxljsreplicaAddrsno longer tears down the cached sentinel client when the replica list is empty, eliminating a continuous rediscovery loop on master-only Sentinel deployments that flooded logs and added per-operation latency (#3795) by @shahyash2609CloseConnhooks:Pool.CloseConnnow triggers registered hooks, fixing a memory leak when connections are closed explicitly rather than via the normal removal path (#3818) by @ndyakovdial tcperrors are now correctly classified as redirectable so cluster routing can recover from a single unreachable node (#3810) by @vladisa88Closehealth checks:ConnPool.Closenow only runs health checks against idle connections, avoiding spurious activity on connections still in use (#3805) by @ndyakovVLINKS/VLINKSWITHSCORESvector-set replies (#3820) by @romanpovol🧪 Testing & Infrastructure
waitForSentinelClusterStablepost-conditions: The sentinel test harness now waits for replicas to be fully connected (not just present in the count) and is robust to randomized spec ordering after failover specs, eliminating an intermittentExpected master to equal slaveflake (#3830) by @ndyakovgovulncheckworkflow: New scheduled GitHub Actions workflow runsgovulncheckon every push, PR, and weekly, surfacing newly disclosed Go vulnerabilities even when no code changes (#3779) by @solardome🧰 Maintenance
Cmd.Slot()lookup refactor: Caches the per-commandCommandInfoand short-circuits keyless commands before the switch dispatch, removing redundantPeekcalls (#3804) by @retr0-kernelmath/rand: Replacedinternal/randwithmath/randfrom the standard library now that the minimum Go version is 1.24 (#3823) by @cxljsConnPool, trimming the pool's footprint (#3826) by @cxljsextra/*package (#3817) by @ndyakov👥 Contributors
We'd like to thank all the contributors who worked on this release!
@cxljs, @DengY11, @elena-kolevska, @Khukharr, @LINKIWI, @ndyakov, @obiyang, @ofekshenawa, @retr0-kernel, @romanpovol, @shahyash2609, @solardome, @vladisa88
Full Changelog: https://github.com/redis/go-redis/compare/v9.19.0...v9.20.0
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.