From 1bb9e0d130f3c6acb602d6d9f1ca4acebbe96677 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:52:56 +0200 Subject: [PATCH 1/5] chore(scripts: fix help call in tag.sh (#3606) --- scripts/tag.sh | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/scripts/tag.sh b/scripts/tag.sh index 5b637637..62b28e99 100755 --- a/scripts/tag.sh +++ b/scripts/tag.sh @@ -4,9 +4,25 @@ set -e DRY_RUN=1 +helps() { + cat <<- EOF +Usage: $0 TAGVERSION [-t] + +Creates git tags for public Go packages. + +ARGUMENTS: + TAGVERSION Tag version to create, for example v1.0.0 + +OPTIONS: + -t Execute git commands (default: dry run) +EOF + exit 0 +} + + if [ $# -eq 0 ]; then echo "Error: Tag version is required" - help + helps fi TAG=$1 @@ -24,20 +40,6 @@ while getopts "t" opt; do esac done -help() { - cat <<- EOF -Usage: $0 TAGVERSION [-t] - -Creates git tags for public Go packages. - -ARGUMENTS: - TAGVERSION Tag version to create, for example v1.0.0 - -OPTIONS: - -t Execute git commands (default: dry run) -EOF - exit 0 -} if [ "$DRY_RUN" -eq 1 ]; then echo "Running in dry-run mode" From 63908223ca0e4919396e33cbb27b8fa823b67793 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:18:34 +0200 Subject: [PATCH 2/5] fix(time): remove cached time optimization (#3611) --- internal/pool/conn.go | 15 +++--- internal/pool/global_time_cache.go | 74 ------------------------------ internal/pool/pool.go | 6 --- 3 files changed, 8 insertions(+), 87 deletions(-) delete mode 100644 internal/pool/global_time_cache.go diff --git a/internal/pool/conn.go b/internal/pool/conn.go index 7682aa87..95d83bfd 100644 --- a/internal/pool/conn.go +++ b/internal/pool/conn.go @@ -27,16 +27,17 @@ var ( errConnNotAvailableForWrite = errors.New("redis: connection not available for write operation") ) -// getCachedTimeNs returns the current time in nanoseconds from the global cache. -// This is updated every 50ms by a background goroutine, avoiding expensive syscalls. -// Max staleness: 50ms. +// getCachedTimeNs returns the current time in nanoseconds. +// This function previously used a global cache updated by a background goroutine, +// but that caused unnecessary CPU usage when the client was idle (ticker waking up +// the scheduler every 50ms). We now use time.Now() directly, which is fast enough +// on modern systems (vDSO on Linux) and only adds ~1-2% overhead in extreme +// high-concurrency benchmarks while eliminating idle CPU usage. func getCachedTimeNs() int64 { - return globalTimeCache.nowNs.Load() + return time.Now().UnixNano() } -// GetCachedTimeNs returns the current time in nanoseconds from the global cache. -// This is updated every 50ms by a background goroutine, avoiding expensive syscalls. -// Max staleness: 50ms. +// GetCachedTimeNs returns the current time in nanoseconds. // Exported for use by other packages that need fast time access. func GetCachedTimeNs() int64 { return getCachedTimeNs() diff --git a/internal/pool/global_time_cache.go b/internal/pool/global_time_cache.go deleted file mode 100644 index d7d21ea7..00000000 --- a/internal/pool/global_time_cache.go +++ /dev/null @@ -1,74 +0,0 @@ -package pool - -import ( - "sync" - "sync/atomic" - "time" -) - -// Global time cache updated every 50ms by background goroutine. -// This avoids expensive time.Now() syscalls in hot paths like getEffectiveReadTimeout. -// Max staleness: 50ms, which is acceptable for timeout deadline checks (timeouts are typically 3-30 seconds). -var globalTimeCache struct { - nowNs atomic.Int64 - lock sync.Mutex - started bool - stop chan struct{} - subscribers int32 -} - -func subscribeToGlobalTimeCache() { - globalTimeCache.lock.Lock() - globalTimeCache.subscribers += 1 - globalTimeCache.lock.Unlock() -} - -func unsubscribeFromGlobalTimeCache() { - globalTimeCache.lock.Lock() - globalTimeCache.subscribers -= 1 - globalTimeCache.lock.Unlock() -} - -func startGlobalTimeCache() { - globalTimeCache.lock.Lock() - if globalTimeCache.started { - globalTimeCache.lock.Unlock() - return - } - - globalTimeCache.started = true - globalTimeCache.nowNs.Store(time.Now().UnixNano()) - globalTimeCache.stop = make(chan struct{}) - globalTimeCache.lock.Unlock() - // Start background updater - go func(stopChan chan struct{}) { - ticker := time.NewTicker(50 * time.Millisecond) - defer ticker.Stop() - - for range ticker.C { - select { - case <-stopChan: - return - default: - } - globalTimeCache.nowNs.Store(time.Now().UnixNano()) - } - }(globalTimeCache.stop) -} - -// stopGlobalTimeCache stops the global time cache if there are no subscribers. -// This should only be called when the last subscriber is removed. -func stopGlobalTimeCache() { - globalTimeCache.lock.Lock() - if !globalTimeCache.started || globalTimeCache.subscribers > 0 { - globalTimeCache.lock.Unlock() - return - } - globalTimeCache.started = false - close(globalTimeCache.stop) - globalTimeCache.lock.Unlock() -} - -func init() { - startGlobalTimeCache() -} diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 50663d7c..184321c1 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -178,9 +178,6 @@ func NewConnPool(opt *Options) *ConnPool { p.connsMu.Unlock() } - startGlobalTimeCache() - subscribeToGlobalTimeCache() - return p } @@ -981,9 +978,6 @@ func (p *ConnPool) Close() error { return ErrClosed } - unsubscribeFromGlobalTimeCache() - stopGlobalTimeCache() - var firstErr error p.connsMu.Lock() for _, cn := range p.conns { From 8549116d8a7553e128a3de9c262b48990d80f403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:55:47 +0200 Subject: [PATCH 3/5] chore(deps): bump actions/checkout from 5 to 6 (#3610) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [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/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/doctests.yaml | 2 +- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/spellcheck.yml | 2 +- .github/workflows/test-redis-enterprise.yml | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e4db94e..b3fc8136 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,7 +32,7 @@ jobs: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Test environment env: @@ -83,7 +83,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Run tests uses: ./.github/actions/run-tests diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 81853524..353581e5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/doctests.yaml b/.github/workflows/doctests.yaml index e645afb9..55d022ed 100644 --- a/.github/workflows/doctests.yaml +++ b/.github/workflows/doctests.yaml @@ -36,7 +36,7 @@ jobs: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Test doc examples working-directory: ./doctests diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 458ae340..34b10b63 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -20,7 +20,7 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: golangci-lint uses: golangci/golangci-lint-action@v9.0.0 with: diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index d2efad8d..05932d60 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Check Spelling uses: rojopolis/spellcheck-github-actions@0.54.0 with: diff --git a/.github/workflows/test-redis-enterprise.yml b/.github/workflows/test-redis-enterprise.yml index faf62902..a84e1f78 100644 --- a/.github/workflows/test-redis-enterprise.yml +++ b/.github/workflows/test-redis-enterprise.yml @@ -20,10 +20,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Clone Redis EE docker repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: RedisLabs/redis-ee-docker path: redis-ee From fd437cea4fb569a15d2a2dcb8b4969e63c28c157 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:56:08 +0200 Subject: [PATCH 4/5] chore(deps): bump golangci/golangci-lint-action from 9.0.0 to 9.1.0 (#3609) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 9.0.0 to 9.1.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v9.0.0...v9.1.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-version: 9.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> --- .github/workflows/golangci-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 34b10b63..97e2b8d6 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@v6 - name: golangci-lint - uses: golangci/golangci-lint-action@v9.0.0 + uses: golangci/golangci-lint-action@v9.1.0 with: verify: true From b362eb7f7d1f4b8aea6759ceea22dcaba9992b4b Mon Sep 17 00:00:00 2001 From: Marco Ferrer <35935108+marcoferrer@users.noreply.github.com> Date: Tue, 25 Nov 2025 07:15:13 -0500 Subject: [PATCH 5/5] fix(txpipeline) add wait to keyless commands list (#3615) --- command.go | 1 + 1 file changed, 1 insertion(+) diff --git a/command.go b/command.go index b99f1312..2dbc2ad8 100644 --- a/command.go +++ b/command.go @@ -64,6 +64,7 @@ var keylessCommands = map[string]struct{}{ "sync": {}, "unsubscribe": {}, "unwatch": {}, + "wait": {}, } type Cmder interface {