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

use min timeout to avoid waiting for too long

This commit is contained in:
Nedyalko Dyakov
2025-11-29 00:54:00 +02:00
parent 4274cffa9d
commit c80f50b528
2 changed files with 26 additions and 229 deletions

View File

@@ -399,10 +399,33 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
if finalState == pool.StateInitializing {
// Another goroutine is initializing - WAIT for it to complete
// Use the request context directly to respect the caller's timeout
// This prevents goroutines from waiting longer than their request timeout
// Use a context with timeout = min(remaining command timeout, DialTimeout)
// This prevents waiting too long while respecting the caller's deadline
waitCtx := ctx
dialTimeout := c.opt.DialTimeout
if cmdDeadline, hasCmdDeadline := ctx.Deadline(); hasCmdDeadline {
// Calculate remaining time until command deadline
remainingTime := time.Until(cmdDeadline)
// Use the minimum of remaining time and DialTimeout
if remainingTime < dialTimeout {
// Command deadline is sooner, use it
waitCtx = ctx
} else {
// DialTimeout is shorter, cap the wait at DialTimeout
var cancel context.CancelFunc
waitCtx, cancel = context.WithTimeout(ctx, dialTimeout)
defer cancel()
}
} else {
// No command deadline, use DialTimeout to prevent waiting indefinitely
var cancel context.CancelFunc
waitCtx, cancel = context.WithTimeout(ctx, dialTimeout)
defer cancel()
}
finalState, err := cn.GetStateMachine().AwaitAndTransition(
ctx,
waitCtx,
[]pool.ConnState{pool.StateIdle, pool.StateInUse},
pool.StateIdle, // Target is IDLE (but we're already there, so this is a no-op)
)