Skip to content

Commit

Permalink
[Internal] GlobalEndpointManager: Fixes Memory Leak (#4226)
Browse files Browse the repository at this point in the history
* memory leak fix

* removed commented out code

* changed to async so test would pass, with just static GetPropetiesHelper will get disposed before requests go through

* added thread saftey

* fixed to interlock pattern

---------

Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com>
  • Loading branch information
NaluTripician and kundadebdatta committed Dec 31, 2023
1 parent c555685 commit 02e4f34
Showing 1 changed file with 20 additions and 9 deletions.
29 changes: 20 additions & 9 deletions Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,33 +114,35 @@ public Uri GetHubUri()
/// The 2 additional tasks will go through all the preferred regions in parallel
/// It will return the first success and stop the parallel tasks.
/// </summary>
public static Task<AccountProperties> GetDatabaseAccountFromAnyLocationsAsync(
public static async Task<AccountProperties> GetDatabaseAccountFromAnyLocationsAsync(
Uri defaultEndpoint,
IList<string>? locations,
Func<Uri, Task<AccountProperties>> getDatabaseAccountFn,
CancellationToken cancellationToken)
{
GetAccountPropertiesHelper threadSafeGetAccountHelper = new GetAccountPropertiesHelper(
{
using (GetAccountPropertiesHelper threadSafeGetAccountHelper = new GetAccountPropertiesHelper(
defaultEndpoint,
locations?.GetEnumerator(),
getDatabaseAccountFn,
cancellationToken);

return threadSafeGetAccountHelper.GetAccountPropertiesAsync();
cancellationToken))
{
return await threadSafeGetAccountHelper.GetAccountPropertiesAsync();
}
}

/// <summary>
/// This is a helper class to
/// </summary>
private class GetAccountPropertiesHelper
private class GetAccountPropertiesHelper : IDisposable
{
private readonly CancellationTokenSource CancellationTokenSource;
private readonly Uri DefaultEndpoint;
private readonly IEnumerator<string>? Locations;
private readonly Func<Uri, Task<AccountProperties>> GetDatabaseAccountFn;
private readonly List<Exception> TransientExceptions = new List<Exception>();
private AccountProperties? AccountProperties = null;
private Exception? NonRetriableException = null;
private Exception? NonRetriableException = null;
private int disposeCounter = 0;

public GetAccountPropertiesHelper(
Uri defaultEndpoint,
Expand Down Expand Up @@ -345,7 +347,16 @@ private static bool IsNonRetriableException(Exception exception)
}

return false;
}
}

public void Dispose()
{
if (Interlocked.Increment(ref this.disposeCounter) == 1)
{
this.CancellationTokenSource?.Cancel();
this.CancellationTokenSource?.Dispose();
}
}
}

public virtual Uri ResolveServiceEndpoint(DocumentServiceRequest request)
Expand Down

0 comments on commit 02e4f34

Please sign in to comment.