Skip to content

Commit 2f9f85a

Browse files
committed
wip
1 parent e3b7052 commit 2f9f85a

File tree

7 files changed

+45
-396
lines changed

7 files changed

+45
-396
lines changed

adapters.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (oa *optionsAdapter) NewDialer() func(context.Context) (net.Conn, error) {
7777
baseDialer := oa.options.NewDialer()
7878
return func(ctx context.Context) (net.Conn, error) {
7979
// Extract network and address from the options
80-
network := "tcp"
80+
network := oa.options.Network
8181
addr := oa.options.Addr
8282
return baseDialer(ctx, network, addr)
8383
}

hitless/hitless_manager.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,19 @@ func (hm *HitlessManager) Close() error {
213213
return nil // Already closed
214214
}
215215

216-
// Shutdown the pool hook
217-
err := hm.poolHooksRef.Shutdown(context.Background())
218-
if err != nil {
219-
// was not able to close pool hook, keep closed state false
220-
hm.closed.Store(false)
221-
return err
216+
// Shutdown the pool hook if it exists
217+
if hm.poolHooksRef != nil {
218+
err := hm.poolHooksRef.Shutdown(context.Background())
219+
if err != nil {
220+
// was not able to close pool hook, keep closed state false
221+
hm.closed.Store(false)
222+
return err
223+
}
224+
// Remove the pool hook from the pool
225+
if hm.pool != nil {
226+
hm.pool.RemovePoolHook(hm.poolHooksRef)
227+
}
222228
}
223-
// Remove the pool hook from the pool
224-
hm.pool.RemovePoolHook(hm.poolHooksRef)
225229

226230
// Clear all active operations
227231
hm.activeMovingOps.Range(func(key, value interface{}) bool {

hitless/hitless_manager_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestHitlessManagerRefactoring(t *testing.T) {
7575
config := DefaultConfig()
7676
client := &MockClient{options: &MockOptions{}}
7777

78-
manager, err := NewHitlessManager(client, config)
78+
manager, err := NewHitlessManager(client, nil, config)
7979
if err != nil {
8080
t.Fatalf("Failed to create hitless manager: %v", err)
8181
}
@@ -136,7 +136,7 @@ func TestHitlessManagerRefactoring(t *testing.T) {
136136
config := DefaultConfig()
137137
client := &MockClient{options: &MockOptions{}}
138138

139-
manager, err := NewHitlessManager(client, config)
139+
manager, err := NewHitlessManager(client, nil, config)
140140
if err != nil {
141141
t.Fatalf("Failed to create hitless manager: %v", err)
142142
}
@@ -178,7 +178,7 @@ func TestHitlessManagerRefactoring(t *testing.T) {
178178
config := DefaultConfig()
179179
client := &MockClient{options: &MockOptions{}}
180180

181-
manager, err := NewHitlessManager(client, config)
181+
manager, err := NewHitlessManager(client, nil, config)
182182
if err != nil {
183183
t.Fatalf("Failed to create hitless manager: %v", err)
184184
}

hitless/notification_handler.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strconv"
77
"time"
88

9+
"github.com/redis/go-redis/v9/internal"
910
"github.com/redis/go-redis/v9/internal/interfaces"
1011
"github.com/redis/go-redis/v9/internal/pool"
1112
"github.com/redis/go-redis/v9/push"
@@ -109,26 +110,38 @@ func (snh *NotificationHandler) handleMoving(ctx context.Context, handlerCtx pus
109110
return ErrInvalidNotification
110111
}
111112

112-
// TODO(hitless): if newEndpoint is empty, we should schedule a handoff to the current endpoint in timeS/2 seconds
113+
deadline := time.Now().Add(time.Duration(timeS) * time.Second)
114+
// If newEndpoint is empty, we should schedule a handoff to the current endpoint in timeS/2 seconds
115+
if newEndpoint == "" || newEndpoint == internal.RedisNull {
116+
// same as current endpoint
117+
newEndpoint = snh.manager.options.GetAddr()
118+
// delay the handoff for timeS/2 seconds to the same endpoint
119+
// do this in a goroutine to avoid blocking the notification handler
120+
go func() {
121+
time.Sleep(time.Duration(timeS/2) * time.Second)
122+
snh.markConnForHandoff(poolConn, newEndpoint, seqID, deadline)
123+
}()
124+
return nil
125+
}
126+
127+
return snh.markConnForHandoff(poolConn, newEndpoint, seqID, deadline)
128+
}
113129

114-
// Mark the connection for handoff
115-
if err := poolConn.MarkForHandoff(newEndpoint, seqID); err != nil {
130+
func (snh *NotificationHandler) markConnForHandoff(conn *pool.Conn, newEndpoint string, seqID int64, deadline time.Time) error {
131+
if err := conn.MarkForHandoff(newEndpoint, seqID); err != nil {
116132
// Connection is already marked for handoff, which is acceptable
117133
// This can happen if multiple MOVING notifications are received for the same connection
118134
return nil
119135
}
120-
121136
// Optionally track in hitless manager for monitoring/debugging
122137
if snh.manager != nil {
123-
connID := poolConn.GetID()
124-
deadline := time.Now().Add(time.Duration(timeS) * time.Second)
138+
connID := conn.GetID()
125139

126140
// Track the operation (ignore errors since this is optional)
127141
_ = snh.manager.TrackMovingOperationWithConnID(context.Background(), newEndpoint, deadline, seqID, connID)
128142
} else {
129143
return fmt.Errorf("hitless: manager not initialized")
130144
}
131-
132145
return nil
133146
}
134147

hitless/pool_hook_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ func (mp *mockPool) Stats() *pool.Stats {
9191
return &pool.Stats{}
9292
}
9393

94+
func (mp *mockPool) AddPoolHook(hook pool.PoolHook) {
95+
// Mock implementation - do nothing
96+
}
97+
98+
func (mp *mockPool) RemovePoolHook(hook pool.PoolHook) {
99+
// Mock implementation - do nothing
100+
}
101+
94102
func (mp *mockPool) Close() error {
95103
return nil
96104
}

options.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -640,19 +640,7 @@ func getUserPassword(u *url.URL) (string, string) {
640640
return user, password
641641
}
642642

643-
func newConnPoolConfig(opt *Options) *pool.Config {
644-
return &pool.Config{
645-
PoolFIFO: opt.PoolFIFO || opt.HitlessUpgradeConfig.IsEnabled(), // Always FIFO with hitless upgrades
646-
PoolSize: opt.PoolSize,
647-
PoolTimeout: opt.PoolTimeout,
648-
DialTimeout: opt.DialTimeout,
649-
MinIdleConns: opt.MinIdleConns,
650-
MaxIdleConns: opt.MaxIdleConns,
651-
MaxActiveConns: opt.MaxActiveConns,
652-
ConnMaxIdleTime: opt.ConnMaxIdleTime,
653-
ConnMaxLifetime: opt.ConnMaxLifetime,
654-
}
655-
}
643+
656644

657645
func newConnPool(
658646
opt *Options,

0 commit comments

Comments
 (0)