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.
|
||||
// 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.
|
||||
// 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()
|
||||
//
|
||||
// NOTE: We directly access cn.stateMachine.state here instead of using the state machine's
|
||||
// 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
|
||||
// needs to notify waiters on these transitions, update this to use TryTransitionFast().
|
||||
func (cn *Conn) TryAcquire() bool {
|
||||
// The || operator short-circuits, so only 1 CAS in the common case
|
||||
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.
|
||||
|
||||
@@ -319,6 +319,7 @@ func (cf *ClientFactory) Create(key string, options *CreateClientOptions) (redis
|
||||
}
|
||||
|
||||
var client redis.UniversalClient
|
||||
var opts interface{}
|
||||
|
||||
// Determine if this is a cluster configuration
|
||||
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)
|
||||
} else {
|
||||
// Create single client
|
||||
@@ -379,9 +381,14 @@ func (cf *ClientFactory) Create(key string, options *CreateClientOptions) (redis
|
||||
}
|
||||
}
|
||||
|
||||
opts = 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
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
// Wait for deletion to complete
|
||||
status, err := m.faultInjector.WaitForAction(ctx, resp.ActionID,
|
||||
WithMaxWaitTime(2*time.Minute),
|
||||
|
||||
Reference in New Issue
Block a user