mirror of
https://github.com/redis/go-redis.git
synced 2025-12-02 06:22:31 +03:00
Fix broken initialization of idle connections
This commit is contained in:
@@ -699,20 +699,22 @@ func (cn *Conn) GetStateMachine() *ConnStateMachine {
|
|||||||
// TryAcquire attempts to acquire the connection for use.
|
// TryAcquire attempts to acquire the connection for use.
|
||||||
// This is an optimized inline method for the hot path (Get operation).
|
// This is an optimized inline method for the hot path (Get operation).
|
||||||
//
|
//
|
||||||
// It tries to transition from IDLE -> IN_USE or CREATED -> IN_USE.
|
// It tries to transition from IDLE -> IN_USE or CREATED -> CREATED.
|
||||||
// Returns true if the connection was successfully acquired, false otherwise.
|
// Returns true if the connection was successfully acquired, false otherwise.
|
||||||
|
// The CREATED->CREATED is done so we can keep the state correct for later
|
||||||
|
// initialization of the connection in initConn.
|
||||||
//
|
//
|
||||||
// Performance: This is faster than calling GetStateMachine() + TryTransitionFast()
|
// Performance: This is faster than calling GetStateMachine() + TryTransitionFast()
|
||||||
//
|
//
|
||||||
// NOTE: We directly access cn.stateMachine.state here instead of using the state machine's
|
// NOTE: We directly access cn.stateMachine.state here instead of using the state machine's
|
||||||
// methods. This breaks encapsulation but is necessary for performance.
|
// methods. This breaks encapsulation but is necessary for performance.
|
||||||
// The IDLE->IN_USE and CREATED->IN_USE transitions don't need
|
// The IDLE->IN_USE and CREATED->CREATED transitions don't need
|
||||||
// waiter notification, and benchmarks show 1-3% improvement. If the state machine ever
|
// waiter notification, and benchmarks show 1-3% improvement. If the state machine ever
|
||||||
// needs to notify waiters on these transitions, update this to use TryTransitionFast().
|
// needs to notify waiters on these transitions, update this to use TryTransitionFast().
|
||||||
func (cn *Conn) TryAcquire() bool {
|
func (cn *Conn) TryAcquire() bool {
|
||||||
// The || operator short-circuits, so only 1 CAS in the common case
|
// The || operator short-circuits, so only 1 CAS in the common case
|
||||||
return cn.stateMachine.state.CompareAndSwap(uint32(StateIdle), uint32(StateInUse)) ||
|
return cn.stateMachine.state.CompareAndSwap(uint32(StateIdle), uint32(StateInUse)) ||
|
||||||
cn.stateMachine.state.CompareAndSwap(uint32(StateCreated), uint32(StateInUse))
|
cn.stateMachine.state.CompareAndSwap(uint32(StateCreated), uint32(StateCreated))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases the connection back to the pool.
|
// Release releases the connection back to the pool.
|
||||||
|
|||||||
@@ -319,6 +319,7 @@ func (cf *ClientFactory) Create(key string, options *CreateClientOptions) (redis
|
|||||||
}
|
}
|
||||||
|
|
||||||
var client redis.UniversalClient
|
var client redis.UniversalClient
|
||||||
|
var opts interface{}
|
||||||
|
|
||||||
// Determine if this is a cluster configuration
|
// Determine if this is a cluster configuration
|
||||||
if len(cf.config.Endpoints) > 1 || cf.isClusterEndpoint() {
|
if len(cf.config.Endpoints) > 1 || cf.isClusterEndpoint() {
|
||||||
@@ -349,6 +350,7 @@ func (cf *ClientFactory) Create(key string, options *CreateClientOptions) (redis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts = clusterOptions
|
||||||
client = redis.NewClusterClient(clusterOptions)
|
client = redis.NewClusterClient(clusterOptions)
|
||||||
} else {
|
} else {
|
||||||
// Create single client
|
// Create single client
|
||||||
@@ -379,9 +381,14 @@ func (cf *ClientFactory) Create(key string, options *CreateClientOptions) (redis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts = clientOptions
|
||||||
client = redis.NewClient(clientOptions)
|
client = redis.NewClient(clientOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := client.Ping(context.Background()).Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to connect to Redis: %w\nOptions: %+v", err, opts)
|
||||||
|
}
|
||||||
|
|
||||||
// Store the client
|
// Store the client
|
||||||
cf.clients[key] = client
|
cf.clients[key] = client
|
||||||
|
|
||||||
@@ -832,7 +839,6 @@ func (m *TestDatabaseManager) DeleteDatabase(ctx context.Context) error {
|
|||||||
return fmt.Errorf("failed to trigger database deletion: %w", err)
|
return fmt.Errorf("failed to trigger database deletion: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Wait for deletion to complete
|
// Wait for deletion to complete
|
||||||
status, err := m.faultInjector.WaitForAction(ctx, resp.ActionID,
|
status, err := m.faultInjector.WaitForAction(ctx, resp.ActionID,
|
||||||
WithMaxWaitTime(2*time.Minute),
|
WithMaxWaitTime(2*time.Minute),
|
||||||
|
|||||||
Reference in New Issue
Block a user