Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Respect IReconnectRetryPolicy in disconnect loops #2853

Merged
merged 3 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Current package versions:
| [![StackExchange.Redis](https://img.shields.io/nuget/v/StackExchange.Redis.svg)](https://www.nuget.org/packages/StackExchange.Redis/) | [![StackExchange.Redis](https://img.shields.io/nuget/vpre/StackExchange.Redis.svg)](https://www.nuget.org/packages/StackExchange.Redis/) | [![StackExchange.Redis MyGet](https://img.shields.io/myget/stackoverflow/vpre/StackExchange.Redis.svg)](https://www.myget.org/feed/stackoverflow/package/nuget/StackExchange.Redis) |

## Unreleased
No pending unreleased changes.
- Fix: Respect `IReconnectRetryPolicy` timing in the case that a node that was present disconnects indefinitely ([#2853 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2853))
- Changes max default retry policy backoff to 60 seconds ([#2853 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2853))

## 2.8.24

Expand Down
2 changes: 1 addition & 1 deletion src/StackExchange.Redis/ExponentialRetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace StackExchange.Redis
public class ExponentialRetry : IReconnectRetryPolicy
{
private readonly int deltaBackOffMilliseconds;
private readonly int maxDeltaBackOffMilliseconds = (int)TimeSpan.FromSeconds(10).TotalMilliseconds;
private readonly int maxDeltaBackOffMilliseconds = (int)TimeSpan.FromSeconds(60).TotalMilliseconds;
[ThreadStatic]
private static Random? r;

Expand Down
12 changes: 11 additions & 1 deletion src/StackExchange.Redis/PhysicalBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ internal sealed class PhysicalBridge : IDisposable
private int beating;
private int failConnectCount = 0;
private volatile bool isDisposed;
private volatile bool shouldResetConnectionRetryCount;
private long nonPreferredEndpointCount;

// private volatile int missedHeartbeats;
Expand Down Expand Up @@ -597,6 +598,8 @@ internal void OnHeartbeat(bool ifConnectedOnly)
// We need to time that out and cleanup the PhysicalConnection if needed, otherwise that reader and socket will remain open
// for the lifetime of the application due to being orphaned, yet still referenced by the active task doing the pipe read.
case (int)State.ConnectedEstablished:
// Track that we should reset the count on the next disconnect, but not do so in a loop
shouldResetConnectionRetryCount = true;
var tmp = physical;
if (tmp != null)
{
Expand Down Expand Up @@ -668,7 +671,14 @@ internal void OnHeartbeat(bool ifConnectedOnly)
}
break;
case (int)State.Disconnected:
Interlocked.Exchange(ref connectTimeoutRetryCount, 0);
// Only if we should reset the connection count
// This should only happen after a successful reconnection, and not every time we bounce from BeginConnectAsync -> Disconnected
// in a failure loop case that happens when a node goes missing forever.
if (shouldResetConnectionRetryCount)
{
shouldResetConnectionRetryCount = false;
Interlocked.Exchange(ref connectTimeoutRetryCount, 0);
}
if (!ifConnectedOnly)
{
Multiplexer.Trace("Resurrecting " + ToString());
Expand Down
Loading