Skip to content

fix: Queue batch commands to backlog during MOVED reconnection#3133

Closed
advaMosh wants to merge 1 commit into
StackExchange:mainfrom
advaMosh:fix/batch-backlog-during-reconnect
Closed

fix: Queue batch commands to backlog during MOVED reconnection#3133
advaMosh wants to merge 1 commit into
StackExchange:mainfrom
advaMosh:fix/batch-backlog-during-reconnect

Conversation

@advaMosh

@advaMosh advaMosh commented Jul 21, 2026

Copy link
Copy Markdown

Problem

When a MOVED-to-same-endpoint triggers reconnection (as implemented in PR #3003), batch commands (IBatch) issued during the ~50-100ms reconnection window fail immediately with RedisConnectionException: NoConnectionAvailable. This is because:

  1. RedisBatch.Execute() calls SelectServer() which returns null for disconnected/reconnecting servers.
  2. PhysicalBridge.TryEnqueue() returns false when !IsConnected, unlike TryWriteAsync/TryWriteSync which queue to the backlog via QueueOrFailMessage()BacklogEnqueue().

This creates an inconsistency: individual async commands (e.g. db.StringSetAsync()) are queued and succeed after reconnection, but batch commands throw immediately during the same reconnection window.

Impact

  • Applications using IBatch see 1-3 RedisConnectionException errors per MOVED redirect, while individual commands see zero errors in the same scenario

Fix

RedisBatch.Execute(): When SelectServer() returns null and BacklogPolicy.QueueWhileDisconnected is enabled, retry with allowDisconnected: true to locate the server endpoint. This mirrors the pattern already used in PrepareToPushMessageToBridge().

PhysicalBridge.TryEnqueue(): When !IsConnected || NeedsReconnect and BacklogPolicy.QueueWhileDisconnected is enabled, queue messages to the backlog instead of returning false. This matches the existing behavior of TryWriteSync() and TryWriteAsync() for individual commands.

Testing

  • Before fix: 1-3 NoConnectionAvailable errors per redirect event (batch.Execute throws during ~50-100ms reconnection window)
  • After fix: 0 errors — batch commands are queued to backlog and sent after reconnection completes

The fix was also validated against plain disconnect scenario, where batch commands are similarly queued rather than failing immediately.

Related

When a MOVED-to-same-endpoint triggers reconnection (PR StackExchange#3003), batch
commands issued during the ~50-100ms reconnection window fail immediately
with NoConnectionAvailable. This is because:

1. RedisBatch.Execute() calls SelectServer() which returns null for
   disconnected/reconnecting servers.
2. PhysicalBridge.TryEnqueue() returns false when !IsConnected, unlike
   TryWriteAsync/TryWriteSync which queue to the backlog.

This creates an inconsistency where individual async commands succeed
(queued via BacklogPolicy) but batch commands throw during the same
reconnection window.

Fix:
- RedisBatch.Execute(): When SelectServer returns null and
  BacklogPolicy.QueueWhileDisconnected is enabled, retry with
  allowDisconnected=true to find the server endpoint.
- PhysicalBridge.TryEnqueue(): When disconnected/reconnecting and
  BacklogPolicy.QueueWhileDisconnected is enabled, queue messages to
  the backlog instead of returning false.

This matches the existing behavior of individual command paths and
ensures batch commands are transparently queued and sent after
reconnection completes.

Tested with ElastiCache Serverless proxy redirect scenario:
- Before: 1-3 NoConnectionAvailable errors per MOVED redirect
- After: 0 errors, batch waits for reconnection via backlog
@advaMosh advaMosh closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant