Skip to content

Commit 26b1e89

Browse files
Merge branch 'master' into feat/8.8-xnack
2 parents 475c43d + e7e9866 commit 26b1e89

41 files changed

Lines changed: 1727 additions & 291 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

RELEASE-NOTES.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,96 @@
11
# Release Notes
22

3+
# 9.19.0 (2026-04-27)
4+
5+
## 🚀 Highlights
6+
7+
### FIPS-Compatible Script Helper
8+
9+
`Script` now supports a FIPS-safe execution mode that avoids client-side SHA-1 computation, which is blocked in strict FIPS environments. A new `NewScriptServerSHA` constructor uses `SCRIPT LOAD` to obtain and cache the digest from the server, then runs commands via `EVALSHA`/`EVALSHA_RO`. Falls back to `EVAL`/`EVALRO` if loading fails, and transparently retries once on `NOSCRIPT`. The default behavior is unchanged for existing users.
10+
11+
([#3700](https://github.com/redis/go-redis/pull/3700)) by [@chaitanyabodlapati](https://github.com/chaitanyabodlapati)
12+
13+
### FT.AGGREGATE Step-Based Pipeline Builder
14+
15+
Added a new step-based `FT.AGGREGATE` pipeline API via `FTAggregateOptions.Steps`, allowing `LOAD`, `APPLY`, `GROUPBY`, and `SORTBY` (with per-step `MAX`) to be repeated and interleaved in arbitrary order — matching Redis's native multi-stage aggregation semantics. The legacy `Load`/`Apply`/`GroupBy`/`SortBy`/`SortByMax` fields are now deprecated.
16+
17+
([#3782](https://github.com/redis/go-redis/pull/3782)) by [@ndyakov](https://github.com/ndyakov)
18+
19+
### Raw RESP Protocol Access
20+
21+
Added `DoRaw` and `DoRawWriteTo` methods for executing arbitrary commands and reading the raw RESP response. Useful for proxying, custom protocol inspection, and working with commands not yet wrapped by go-redis.
22+
23+
([#3713](https://github.com/redis/go-redis/pull/3713)) by [@ofekshenawa](https://github.com/ofekshenawa)
24+
25+
### Configurable Dial Retry Backoff
26+
27+
Added `DialerRetryBackoff` option (plumbed through `Options`, `ClusterOptions`, `RingOptions`, `FailoverOptions`) to let callers customize the delay between failed dial attempts. Helpers `DialRetryBackoffConstant` and `DialRetryBackoffExponential` (with jitter and cap) are provided out of the box. Dial timeout is now also applied **per attempt** rather than across all retries.
28+
29+
([#3706](https://github.com/redis/go-redis/pull/3706), [#3705](https://github.com/redis/go-redis/pull/3705)) by [@mwhooker](https://github.com/mwhooker)
30+
31+
## ✨ New Features
32+
33+
- **FT.AGGREGATE Steps**: Step-based pipeline builder for `FT.AGGREGATE` with support for repeated/interleaved `LOAD`, `APPLY`, `GROUPBY`, and `SORTBY` stages ([#3782](https://github.com/redis/go-redis/pull/3782)) by [@ndyakov](https://github.com/ndyakov)
34+
- **VectorSet commands**: Added `VISMEMBER` and `WITHATTRIBS` support ([#3753](https://github.com/redis/go-redis/pull/3753)) by [@romanpovol](https://github.com/romanpovol)
35+
- **FIPS-safe Script**: `NewScriptServerSHA` uses `SCRIPT LOAD` to obtain the digest from the server, avoiding client-side SHA-1 ([#3700](https://github.com/redis/go-redis/pull/3700)) by [@chaitanyabodlapati](https://github.com/chaitanyabodlapati)
36+
- **Raw RESP access**: `DoRaw` and `DoRawWriteTo` for raw RESP protocol access ([#3713](https://github.com/redis/go-redis/pull/3713)) by [@ofekshenawa](https://github.com/ofekshenawa)
37+
- **Dial retry backoff**: `DialerRetryBackoff` function option with constant and exponential helpers ([#3706](https://github.com/redis/go-redis/pull/3706)) by [@mwhooker](https://github.com/mwhooker)
38+
- **Typed NOSCRIPT error**: Redis `NOSCRIPT` replies are now surfaced as a typed error for easier handling ([#3738](https://github.com/redis/go-redis/pull/3738)) by [@LINKIWI](https://github.com/LINKIWI)
39+
- **PubSub ClientSetName**: Added `ClientSetName` method to `PubSub` ([#3727](https://github.com/redis/go-redis/pull/3727)) by [@Flack74](https://github.com/Flack74)
40+
- **ReplicaOf**: New `ReplicaOf` method replaces the deprecated `SlaveOf` ([#3720](https://github.com/redis/go-redis/pull/3720)) by [@Copilot](https://github.com/apps/copilot-swe-agent)
41+
- **HSCAN BinaryUnmarshaler**: `HScan` now supports types implementing `encoding.BinaryUnmarshaler` ([#3768](https://github.com/redis/go-redis/pull/3768)) by [@Aaditya-dubey1](https://github.com/Aaditya-dubey1)
42+
43+
## 🐛 Bug Fixes
44+
45+
- **Auto hostname type detection**: Improved endpoint type detection for maintenance notifications using DNS-based classification; handles empty hosts and expanded private-IP ranges ([#3789](https://github.com/redis/go-redis/pull/3789)) by [@ndyakov](https://github.com/ndyakov)
46+
- **HELLO fallback**: Don't send `CLIENT MAINT_NOTIFICATIONS` handshake when `HELLO` fails and connection falls back to RESP2; fail fast when explicitly enabled with RESP3 ([#3788](https://github.com/redis/go-redis/pull/3788)) by [@ndyakov](https://github.com/ndyakov)
47+
- **Dial TCP retry**: `ShouldRetry` now treats `net.OpError` with `Op == "dial"` timeout errors as safe to retry since no command was sent ([#3787](https://github.com/redis/go-redis/pull/3787)) by [@vladisa88](https://github.com/vladisa88)
48+
- **wrappedOnClose leak**: Fixed resource leak caused by repeatedly wrapping `baseClient` close logic; replaced with a bounded, concurrency-safe named-hook registry ([#3785](https://github.com/redis/go-redis/pull/3785)) by [@ndyakov](https://github.com/ndyakov)
49+
- **Pool Close() on stale connections**: Suppress close errors (e.g., TLS `closeNotify` timeouts) for connections already dropped by the server due to idle timeout ([#3778](https://github.com/redis/go-redis/pull/3778)) by [@ofekshenawa](https://github.com/ofekshenawa)
50+
- **FIFO waiter ordering**: Fixed race in `ConnStateMachine.notifyWaiters` that could wake multiple waiters under a single mutex hold and violate FIFO ordering ([#3777](https://github.com/redis/go-redis/pull/3777)) by [@0x48core](https://github.com/0x48core)
51+
- **Lua READONLY detection**: Detect `READONLY` errors embedded in Lua script error messages on read-only replicas so commands are correctly retried ([#3769](https://github.com/redis/go-redis/pull/3769)) by [@zhengjilei](https://github.com/zhengjilei)
52+
- **VectorScoreSliceCmd RESP2**: Fixed `VSimWithScores`, `VSimWithArgsWithScores`, and `VLinksWithScores` which were broken on RESP2 connections returning flat arrays instead of maps ([#3767](https://github.com/redis/go-redis/pull/3767)) by [@Copilot](https://github.com/apps/copilot-swe-agent)
53+
- **Closed connection handling**: Two fixes for closed connection handling in the pool ([#3764](https://github.com/redis/go-redis/pull/3764)) by [@cxljs](https://github.com/cxljs)
54+
- **ZRangeArgs Rev**: Fixed `ZRangeArgs` with `Rev` + `ByScore`/`ByLex` incorrectly swapping `Start`/`Stop`, breaking `ZRANGESTORE` ([#3751](https://github.com/redis/go-redis/pull/3751)) by [@Copilot](https://github.com/apps/copilot-swe-agent)
55+
- **OTel metric instrument types**: Fixed metric instrument types in `redisotel-native` ([#3743](https://github.com/redis/go-redis/pull/3743)) by [@ofekshenawa](https://github.com/ofekshenawa)
56+
- **Options.clone() data race**: Fixed data race when cloning `Options` ([#3739](https://github.com/redis/go-redis/pull/3739)) by [@rubensayshi](https://github.com/rubensayshi)
57+
- **Connection closure metrics**: Fixed connection closure metrics and enabled all metric groups by default in `redisotel-native` ([#3735](https://github.com/redis/go-redis/pull/3735)) by [@ofekshenawa](https://github.com/ofekshenawa)
58+
- **OTel semconv v1.38.0**: Use metric definition from `otel/semconv/v1.38.0` in `redisotel-native` ([#3731](https://github.com/redis/go-redis/pull/3731)) by [@wzy9607](https://github.com/wzy9607)
59+
- **SETNX semantics**: Use `SET ... NX` instead of the deprecated `SETNX` command ([#3723](https://github.com/redis/go-redis/pull/3723)) by [@ndyakov](https://github.com/ndyakov)
60+
- **TIME keyless routing**: Mark `TIME` as a keyless command for correct cluster routing ([#3722](https://github.com/redis/go-redis/pull/3722)) by [@fatal10110](https://github.com/fatal10110)
61+
- **Dial timeout per retry**: Dial timeout now applies per attempt instead of across all retry attempts combined ([#3705](https://github.com/redis/go-redis/pull/3705)) by [@mwhooker](https://github.com/mwhooker)
62+
- **Cluster metrics attributes**: Fixed `pool.name` being appended per node, which corrupted and dropped user-provided custom attributes ([#3699](https://github.com/redis/go-redis/pull/3699)) by [@Jesse-Bonfire](https://github.com/Jesse-Bonfire)
63+
- **initConn nil dereference**: Fixed nil pointer dereference and potential deadlock in `*baseClient.initConn()`; added explicit nil option guards to client constructors ([#3676](https://github.com/redis/go-redis/pull/3676)) by [@olde-ducke](https://github.com/olde-ducke)
64+
65+
## ⚡ Performance
66+
67+
- **RESP reader**: Optimized RESP reader by eliminating intermediate string allocations ([#3774](https://github.com/redis/go-redis/pull/3774)) by [@Aaditya-dubey1](https://github.com/Aaditya-dubey1)
68+
- **Inline rendezvous hashing**: Replaced `github.com/dgryski/go-rendezvous` dependency with an in-repo implementation in `internal/hashtag`, reducing the dependency graph while preserving algorithm parity ([#3762](https://github.com/redis/go-redis/pull/3762)) by [@bigsk05](https://github.com/bigsk05)
69+
70+
## 🧪 Testing & Infrastructure
71+
72+
- **Release automation**: Added `repository`, `ref`, and `client-libs-test-image-tag` inputs to the `run-tests` composite action; `redis-version` is now optional so unstable builds use `REDIS_VERSION` from the Makefile ([#3749](https://github.com/redis/go-redis/pull/3749)) by [@dariaguy](https://github.com/dariaguy)
73+
- **Go 1.24**: Updated minimum Go version to 1.24 and use `-compat=1.24` in release scripts ([#3714](https://github.com/redis/go-redis/pull/3714), [#3754](https://github.com/redis/go-redis/pull/3754)) by [@ndyakov](https://github.com/ndyakov), [@cxljs](https://github.com/cxljs)
74+
75+
## 🧰 Maintenance
76+
77+
- **Pool state machine**: Removed redundant `Conn.closed` atomic field in favor of the state machine's `StateClosed` ([#3783](https://github.com/redis/go-redis/pull/3783)) by [@cxljs](https://github.com/cxljs)
78+
- **OTel SDK**: Updated OpenTelemetry SDK dependencies in `redisotel`/`redisotel-native` ([#3770](https://github.com/redis/go-redis/pull/3770)) by [@ndyakov](https://github.com/ndyakov)
79+
- **Go 1.21+ built-ins**: Use `maps.Keys`, `slices.Collect`, `slices.Contains`, `clear()`, and `slices.SortFunc` instead of custom helpers ([#3758](https://github.com/redis/go-redis/pull/3758), [#3746](https://github.com/redis/go-redis/pull/3746)) by [@cxljs](https://github.com/cxljs)
80+
- **HGetAll docs**: Added Go doc comment to `HGetAll` describing behavior and complexity ([#3776](https://github.com/redis/go-redis/pull/3776)) by [@0x48core](https://github.com/0x48core)
81+
- **Docs links**: Fixed irrelevant docs links ([#3724](https://github.com/redis/go-redis/pull/3724)) by [@olzhas-sabiyev](https://github.com/olzhas-sabiyev)
82+
- **Examples cleanup**: Removed throughput binary from examples ([#3733](https://github.com/redis/go-redis/pull/3733)) by [@ndyakov](https://github.com/ndyakov)
83+
84+
## 👥 Contributors
85+
86+
We'd like to thank all the contributors who worked on this release!
87+
88+
[@0x48core](https://github.com/0x48core), [@Aaditya-dubey1](https://github.com/Aaditya-dubey1), [@Copilot](https://github.com/apps/copilot-swe-agent), [@Flack74](https://github.com/Flack74), [@Jesse-Bonfire](https://github.com/Jesse-Bonfire), [@LINKIWI](https://github.com/LINKIWI), [@bigsk05](https://github.com/bigsk05), [@chaitanyabodlapati](https://github.com/chaitanyabodlapati), [@cxljs](https://github.com/cxljs), [@dariaguy](https://github.com/dariaguy), [@fatal10110](https://github.com/fatal10110), [@mwhooker](https://github.com/mwhooker), [@ndyakov](https://github.com/ndyakov), [@ofekshenawa](https://github.com/ofekshenawa), [@olde-ducke](https://github.com/olde-ducke), [@olzhas-sabiyev](https://github.com/olzhas-sabiyev), [@romanpovol](https://github.com/romanpovol), [@rubensayshi](https://github.com/rubensayshi), [@vladisa88](https://github.com/vladisa88), [@wzy9607](https://github.com/wzy9607), [@zhengjilei](https://github.com/zhengjilei)
89+
90+
---
91+
92+
**Full Changelog**: https://github.com/redis/go-redis/compare/v9.18.0...v9.19.0
93+
394
# 9.18.0 (2026-02-16)
495

596
## 🚀 Highlights

RELEASING.md

Lines changed: 136 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,146 @@
11
# Releasing
22

3-
1. Run `release.sh` script which updates versions in go.mod files and pushes a new branch to GitHub:
3+
This document is the runbook for cutting a go-redis release. It is intended
4+
for maintainers with write/tag access to the repository.
5+
6+
For the format and style of the release notes themselves, see
7+
[.github/RELEASE_NOTES_TEMPLATE.md](./.github/RELEASE_NOTES_TEMPLATE.md).
8+
9+
## Versioning
10+
11+
go-redis follows [Semantic Versioning](https://semver.org/):
12+
13+
- **Patch** (`vX.Y.Z+1`) — bug fixes, no API changes.
14+
- **Minor** (`vX.Y+1.0`) — backwards-compatible new features, deprecations.
15+
- **Major** (`vX+1.0.0`) — breaking changes. Coordinate with the team first.
16+
17+
Pre-releases use `vX.Y.Z-beta.N` / `vX.Y.Z-rc.N`.
18+
19+
## Pre-release checklist
20+
21+
- [ ] Target branch is `master` and CI is green on the latest commit.
22+
- [ ] All PRs intended for this release are merged.
23+
- [ ] There are no open issues in the release milestone (if used).
24+
- [ ] `CHANGELOG` / release notes have been considered; dependabot-only
25+
and doc-only changes are excluded per the template.
26+
- [ ] Confirm the next version number and decide if it's a patch / minor / major.
27+
28+
## 1. Draft the release notes
29+
30+
1. Open the draft release auto-generated by
31+
[release-drafter](.github/release-drafter-config.yml) on GitHub.
32+
2. Prepend a new section to [`RELEASE-NOTES.md`](./RELEASE-NOTES.md) using
33+
[`.github/RELEASE_NOTES_TEMPLATE.md`](./.github/RELEASE_NOTES_TEMPLATE.md)
34+
as the format. Keep the file in chronological order (newest first).
35+
3. Pick 3–5 **Highlights** — the most user-facing, impactful changes.
36+
4. Remove dependabot bumps and doc-only typo fixes from the lists.
37+
5. Verify every PR has a contributor attribution and link.
38+
6. Open a PR with just the release-notes change if you want review before
39+
bumping versions, otherwise include it in the release PR below.
40+
41+
## 2. Bump versions and open the release PR
42+
43+
Create a release branch from `master`:
44+
45+
```shell
46+
git checkout master && git pull --ff-only
47+
git checkout -b release/vX.Y.Z
48+
```
49+
50+
Run the release script on that branch:
451

552
```shell
6-
TAG=v1.0.0 ./scripts/release.sh
53+
TAG=vX.Y.Z ./scripts/release.sh
754
```
855

9-
2. Open a pull request and wait for the build to finish.
56+
What the script does (and explicitly does **not** do):
1057

11-
3. Merge the pull request and run `tag.sh` to create tags for packages:
58+
- ✅ Validates `TAG` matches the semver regex and isn't already a git tag.
59+
- ✅ Rewrites every `redis/go-redis*` line in every sub-module `go.mod` to
60+
point at the new `TAG`. Trailing `// indirect` markers are preserved.
61+
- ✅ Runs `go mod tidy -compat=1.24` in each sub-module.
62+
- ✅ Updates the return value in [`version.go`](./version.go).
63+
- ❌ Does **not** switch branches (runs in your current branch).
64+
- ❌ Does **not** require a clean working tree (so you can mix it with
65+
release-notes edits in the same branch).
66+
- ❌ Does **not** commit, tag, or push anything.
67+
68+
Review and commit the changes yourself:
1269

1370
```shell
14-
TAG=v1.0.0 ./scripts/tag.sh
71+
git diff # sanity-check the bumps
72+
git add -u
73+
git commit -m "chore: release vX.Y.Z"
74+
git push origin release/vX.Y.Z
1575
```
76+
77+
Then on GitHub:
78+
79+
- [ ] Open a PR from `release/vX.Y.Z` into `master`.
80+
- [ ] Wait for all required CI checks (build, golangci-lint, spellcheck,
81+
doctests, e2e where applicable) to pass.
82+
- [ ] Get at least one maintainer approval.
83+
- [ ] Merge the PR (use a merge commit — the tag will point at the merge SHA).
84+
85+
## 3. Tag the release
86+
87+
After the release PR is merged, pull the latest `master` and dry-run the
88+
tagger:
89+
90+
```shell
91+
git checkout master && git pull --ff-only
92+
TAG=vX.Y.Z ./scripts/tag.sh vX.Y.Z
93+
```
94+
95+
The script defaults to **dry-run** and prints the commands it would run.
96+
Verify the output, then apply for real with `-t`:
97+
98+
```shell
99+
./scripts/tag.sh vX.Y.Z -t
100+
```
101+
102+
This creates and pushes:
103+
- The top-level tag `vX.Y.Z`.
104+
- A per-module tag `<module>/vX.Y.Z` for each public sub-module
105+
(skipping `example/*` and `internal/*`).
106+
107+
## 4. Publish the GitHub release
108+
109+
1. On GitHub, open the draft release created by release-drafter.
110+
2. Set the tag to `vX.Y.Z` and the target to `master`.
111+
3. Replace the auto-generated body with the curated notes from
112+
`RELEASE-NOTES.md` for this version.
113+
4. For pre-releases, check **"Set as a pre-release"**.
114+
5. Publish.
115+
116+
## 5. Post-release
117+
118+
- [ ] Verify the release appears on
119+
[pkg.go.dev](https://pkg.go.dev/github.com/redis/go-redis/v9) within
120+
a few minutes (trigger a fetch by visiting the version URL if needed).
121+
- [ ] Announce on Discord (see the link in `CONTRIBUTING.md`).
122+
- [ ] Close the release milestone if one was used.
123+
- [ ] Open follow-up issues for anything deferred from this release.
124+
125+
## Hotfix / patch release
126+
127+
For an urgent fix on top of the latest release:
128+
129+
1. Branch from the latest release tag: `git checkout -b hotfix/vX.Y.Z+1 vX.Y.Z`.
130+
2. Cherry-pick (or re-apply) only the required fix commits.
131+
3. Follow the normal release flow above with `TAG=vX.Y.Z+1`.
132+
4. Make sure the fix is also present on `master` (forward-port if necessary).
133+
134+
## Troubleshooting
135+
136+
- **`release.sh` fails with "tag already exists"** — the tag has already
137+
been created. Pick the next version, or delete the local tag first if
138+
it was created by mistake.
139+
- **`tag.sh` reports version mismatch in a `go.mod`** — a sub-module was
140+
not updated by `release.sh`. Fix the `go.mod` manually (or re-run
141+
`release.sh`), amend the release PR, and re-run the tagger.
142+
- **`version.go` does not contain the tag**`release.sh` did not run or
143+
the bump was reverted. Re-run `release.sh` on the release branch.
144+
- **pkg.go.dev does not show the new version** — visit
145+
`https://pkg.go.dev/github.com/redis/go-redis/[email protected]` once to trigger
146+
a fetch from the module proxy.

0 commit comments

Comments
 (0)