Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
5649ffb
feat(hitless): Introduce handlers for hitless upgrades
ndyakov Aug 18, 2025
c6f4820
Update pubsub.go
ndyakov Aug 19, 2025
5574793
Update redis.go
ndyakov Aug 19, 2025
ded98ec
address comments
ndyakov Aug 19, 2025
fd98a22
Update internal/pool/pool.go
ndyakov Aug 19, 2025
1f8b660
Update internal/pool/pool.go
ndyakov Aug 19, 2025
e846e5a
Update tx.go
ndyakov Aug 19, 2025
22da2b5
address comments
ndyakov Aug 19, 2025
adee0a8
fix logger
ndyakov Aug 19, 2025
2e47e39
address pr comments
ndyakov Aug 21, 2025
26923a2
refactor for readibility
ndyakov Aug 21, 2025
4940827
refactor for readibility x2
ndyakov Aug 21, 2025
0fd9871
filter out logging
ndyakov Aug 21, 2025
c31ec64
check err on requeue
ndyakov Aug 21, 2025
e596dd7
fix test logger
ndyakov Aug 21, 2025
6031458
fix test
ndyakov Aug 21, 2025
b2228f4
fix tests
ndyakov Aug 21, 2025
30fceb8
fix hooks and add logging, logging will be removed before merge
ndyakov Aug 22, 2025
bfca15a
update example and tests, drop connectionAdapter
ndyakov Aug 22, 2025
3615779
fix example tests, pop more connections
ndyakov Aug 25, 2025
5f608ca
fix push processor exposed in opts
ndyakov Aug 25, 2025
7bec972
update config
ndyakov Aug 26, 2025
b5c1ced
improve logging
ndyakov Aug 27, 2025
7801166
improve test logging
ndyakov Aug 27, 2025
e94b0a5
pool fix
ndyakov Aug 27, 2025
418c1f3
fix log order
ndyakov Aug 27, 2025
18150e4
log level as const
ndyakov Aug 28, 2025
f9af430
pooling fix
ndyakov Aug 28, 2025
b65bc6e
bugfixes and default config optimization
ndyakov Aug 29, 2025
22e1d74
fix break of in dial
ndyakov Aug 29, 2025
5bc0711
fix tests
ndyakov Aug 29, 2025
3c1b880
fix linter
ndyakov Aug 29, 2025
b5e5760
actually, remove active op log
ndyakov Aug 29, 2025
f329fd5
remove some logs
ndyakov Aug 29, 2025
63c2290
cleaner default config
ndyakov Aug 29, 2025
919cc6a
cleanup and doc
ndyakov Aug 29, 2025
208ca70
disable logger for cleaner test output
ndyakov Aug 29, 2025
bdeda87
default log for hitless to errors only
ndyakov Aug 29, 2025
74164a4
fix flaky test?
ndyakov Aug 29, 2025
1ab25f2
cleanup the logging a bit
ndyakov Aug 29, 2025
81de5aa
update README
ndyakov Aug 29, 2025
e6d4b46
fix build
ndyakov Aug 29, 2025
b42c19b
add additional options for dialer retries
ndyakov Sep 1, 2025
73ff273
fix race in test
ndyakov Sep 1, 2025
b34f827
separate worker from pool hook
ndyakov Sep 2, 2025
32ddb96
example circuit breaker implementation, fast fail on big pools
ndyakov Sep 2, 2025
ecfdb18
configurable circuit breaker
ndyakov Sep 3, 2025
d8b8edc
potential bug fixes
ndyakov Sep 3, 2025
1376f85
cover corner case
ndyakov Sep 3, 2025
bdbd5cf
use switch
ndyakov Sep 3, 2025
1d474ab
remove copilot instructions
ndyakov Sep 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ coverage.txt
**/coverage.txt
.vscode
tmp/*

# Hitless upgrade documentation (temporary)
hitless/docs/
111 changes: 111 additions & 0 deletions adapters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package redis

import (
"context"
"errors"
"net"
"time"

"github.com/redis/go-redis/v9/internal/interfaces"
"github.com/redis/go-redis/v9/push"
)

// ErrInvalidCommand is returned when an invalid command is passed to ExecuteCommand.
var ErrInvalidCommand = errors.New("invalid command type")

// ErrInvalidPool is returned when the pool type is not supported.
var ErrInvalidPool = errors.New("invalid pool type")

// newClientAdapter creates a new client adapter for regular Redis clients.
func newClientAdapter(client *baseClient) interfaces.ClientInterface {
return &clientAdapter{client: client}
}

// clientAdapter adapts a Redis client to implement interfaces.ClientInterface.
type clientAdapter struct {
client *baseClient
}

// GetOptions returns the client options.
func (ca *clientAdapter) GetOptions() interfaces.OptionsInterface {
return &optionsAdapter{options: ca.client.opt}
}

// GetPushProcessor returns the client's push notification processor.
func (ca *clientAdapter) GetPushProcessor() interfaces.NotificationProcessor {
return &pushProcessorAdapter{processor: ca.client.pushProcessor}
}

// optionsAdapter adapts Redis options to implement interfaces.OptionsInterface.
type optionsAdapter struct {
options *Options
}

// GetReadTimeout returns the read timeout.
func (oa *optionsAdapter) GetReadTimeout() time.Duration {
return oa.options.ReadTimeout
}

// GetWriteTimeout returns the write timeout.
func (oa *optionsAdapter) GetWriteTimeout() time.Duration {
return oa.options.WriteTimeout
}

// GetNetwork returns the network type.
func (oa *optionsAdapter) GetNetwork() string {
return oa.options.Network
}

// GetAddr returns the connection address.
func (oa *optionsAdapter) GetAddr() string {
return oa.options.Addr
}

// IsTLSEnabled returns true if TLS is enabled.
func (oa *optionsAdapter) IsTLSEnabled() bool {
return oa.options.TLSConfig != nil
}

// GetProtocol returns the protocol version.
func (oa *optionsAdapter) GetProtocol() int {
return oa.options.Protocol
}

// GetPoolSize returns the connection pool size.
func (oa *optionsAdapter) GetPoolSize() int {
return oa.options.PoolSize
}

// NewDialer returns a new dialer function for the connection.
func (oa *optionsAdapter) NewDialer() func(context.Context) (net.Conn, error) {
baseDialer := oa.options.NewDialer()
return func(ctx context.Context) (net.Conn, error) {
// Extract network and address from the options
network := oa.options.Network
addr := oa.options.Addr
return baseDialer(ctx, network, addr)
}
}

// pushProcessorAdapter adapts a push.NotificationProcessor to implement interfaces.NotificationProcessor.
type pushProcessorAdapter struct {
processor push.NotificationProcessor
}

// RegisterHandler registers a handler for a specific push notification name.
func (ppa *pushProcessorAdapter) RegisterHandler(pushNotificationName string, handler interface{}, protected bool) error {
if pushHandler, ok := handler.(push.NotificationHandler); ok {
return ppa.processor.RegisterHandler(pushNotificationName, pushHandler, protected)
}
return errors.New("handler must implement push.NotificationHandler")
}

// UnregisterHandler removes a handler for a specific push notification name.
func (ppa *pushProcessorAdapter) UnregisterHandler(pushNotificationName string) error {
return ppa.processor.UnregisterHandler(pushNotificationName)
}

// GetHandler returns the handler for a specific push notification name.
func (ppa *pushProcessorAdapter) GetHandler(pushNotificationName string) interface{} {
return ppa.processor.GetHandler(pushNotificationName)
}
Loading
Loading