1
0
mirror of https://github.com/redis/go-redis.git synced 2025-12-02 06:22:31 +03:00

Merge branch 'ndyakov/optional-logger' into optional-logger

This commit is contained in:
Nedyalko Dyakov
2025-11-25 15:41:42 +02:00
committed by GitHub
11 changed files with 35 additions and 111 deletions

View File

@@ -32,7 +32,7 @@ jobs:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Setup Test environment - name: Setup Test environment
env: env:
@@ -83,7 +83,7 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Run tests - name: Run tests
uses: ./.github/actions/run-tests uses: ./.github/actions/run-tests

View File

@@ -35,7 +35,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@@ -36,7 +36,7 @@ jobs:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Test doc examples - name: Test doc examples
working-directory: ./doctests working-directory: ./doctests

View File

@@ -20,9 +20,9 @@ jobs:
name: lint name: lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v9.0.0 uses: golangci/golangci-lint-action@v9.1.0
with: with:
verify: true verify: true

View File

@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Check Spelling - name: Check Spelling
uses: rojopolis/spellcheck-github-actions@0.54.0 uses: rojopolis/spellcheck-github-actions@0.54.0
with: with:

View File

@@ -20,10 +20,10 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Clone Redis EE docker repository - name: Clone Redis EE docker repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: RedisLabs/redis-ee-docker repository: RedisLabs/redis-ee-docker
path: redis-ee path: redis-ee

View File

@@ -64,6 +64,7 @@ var keylessCommands = map[string]struct{}{
"sync": {}, "sync": {},
"unsubscribe": {}, "unsubscribe": {},
"unwatch": {}, "unwatch": {},
"wait": {},
} }
type Cmder interface { type Cmder interface {

View File

@@ -27,16 +27,17 @@ var (
errConnNotAvailableForWrite = errors.New("redis: connection not available for write operation") errConnNotAvailableForWrite = errors.New("redis: connection not available for write operation")
) )
// getCachedTimeNs returns the current time in nanoseconds from the global cache. // getCachedTimeNs returns the current time in nanoseconds.
// This is updated every 50ms by a background goroutine, avoiding expensive syscalls. // This function previously used a global cache updated by a background goroutine,
// Max staleness: 50ms. // 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 { func getCachedTimeNs() int64 {
return globalTimeCache.nowNs.Load() return time.Now().UnixNano()
} }
// GetCachedTimeNs returns the current time in nanoseconds from the global cache. // GetCachedTimeNs returns the current time in nanoseconds.
// This is updated every 50ms by a background goroutine, avoiding expensive syscalls.
// Max staleness: 50ms.
// Exported for use by other packages that need fast time access. // Exported for use by other packages that need fast time access.
func GetCachedTimeNs() int64 { func GetCachedTimeNs() int64 {
return getCachedTimeNs() return getCachedTimeNs()

View File

@@ -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()
}

View File

@@ -182,9 +182,6 @@ func NewConnPool(opt *Options) *ConnPool {
p.connsMu.Unlock() p.connsMu.Unlock()
} }
startGlobalTimeCache()
subscribeToGlobalTimeCache()
return p return p
} }
@@ -985,9 +982,6 @@ func (p *ConnPool) Close() error {
return ErrClosed return ErrClosed
} }
unsubscribeFromGlobalTimeCache()
stopGlobalTimeCache()
var firstErr error var firstErr error
p.connsMu.Lock() p.connsMu.Lock()
for _, cn := range p.conns { for _, cn := range p.conns {

View File

@@ -4,9 +4,25 @@ set -e
DRY_RUN=1 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 if [ $# -eq 0 ]; then
echo "Error: Tag version is required" echo "Error: Tag version is required"
help helps
fi fi
TAG=$1 TAG=$1
@@ -24,20 +40,6 @@ while getopts "t" opt; do
esac esac
done 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 if [ "$DRY_RUN" -eq 1 ]; then
echo "Running in dry-run mode" echo "Running in dry-run mode"