Expected Behavior
When ContextTimeoutEnabled is enabled and a caller context deadline expires, go-redis should be able to return ctx.Err() without always closing the underlying pooled connection, as long as the connection can be brought back into RESP sync safely.
Current Behavior
Context cancellation/deadline errors are treated as bad connection errors. If a command times out via context, the connection is removed from the pool and closed.
This is safe, but expensive for Redis over TLS because frequent context deadlines can cause frequent TCP/TLS reconnects.
Possible Solution
Add an opt-in mode, for example:
DrainOnContextTimeout bool
ContextTimeoutDrainTimeout time.Duration
Behavior:
- Return
ctx.Err() to the caller when the caller context expires.
- Keep the connection out of the pool.
- Continue reading/discarding the outstanding Redis response under a bounded internal timeout.
- If drain succeeds, return the connection to the pool.
- If drain fails or times out, close/remove the connection as today.
Steps to Reproduce
- Use go-redis with
ContextTimeoutEnabled: true.
- Connect to Redis over TLS.
- Run commands with short context deadlines.
- Observe that timed-out operations close pooled connections and trigger new TLS handshakes.
Context (Environment)
- go-redis version: v9 / main
- Redis version: Redis 7+
- Use case: short caller deadlines under load
Detailed Description
The goal is not to ignore caller cancellation. The user-facing command should still finish with context.DeadlineExceeded / context.Canceled when the caller context expires.
The proposed change is only about what happens to the already-written command's connection after that point. Instead of immediately closing the connection, the client can keep that connection unavailable to other callers while it tries to consume and discard the outstanding RESP reply. If that cleanup succeeds, the connection can be reused; otherwise it should still be closed.
Possible Implementation
For commands that were successfully written, read the response using an internal timeout after the caller context expires. Mark the connection reusable only if the read/drain completes successfully.
I have a prototype and can open a PR if this direction is acceptable.
Expected Behavior
When
ContextTimeoutEnabledis enabled and a caller context deadline expires, go-redis should be able to returnctx.Err()without always closing the underlying pooled connection, as long as the connection can be brought back into RESP sync safely.Current Behavior
Context cancellation/deadline errors are treated as bad connection errors. If a command times out via context, the connection is removed from the pool and closed.
This is safe, but expensive for Redis over TLS because frequent context deadlines can cause frequent TCP/TLS reconnects.
Possible Solution
Add an opt-in mode, for example:
Behavior:
ctx.Err()to the caller when the caller context expires.Steps to Reproduce
ContextTimeoutEnabled: true.Context (Environment)
Detailed Description
The goal is not to ignore caller cancellation. The user-facing command should still finish with
context.DeadlineExceeded/context.Canceledwhen the caller context expires.The proposed change is only about what happens to the already-written command's connection after that point. Instead of immediately closing the connection, the client can keep that connection unavailable to other callers while it tries to consume and discard the outstanding RESP reply. If that cleanup succeeds, the connection can be reused; otherwise it should still be closed.
Possible Implementation
For commands that were successfully written, read the response using an internal timeout after the caller context expires. Mark the connection reusable only if the read/drain completes successfully.
I have a prototype and can open a PR if this direction is acceptable.