Skip to content

Commit

Permalink
GlobalEndpointManager: Fixes Unobserved and Unhandled Exception from …
Browse files Browse the repository at this point in the history
…Getting Thrown (#4241)

* Code changes to add continuation token for account properties task.

* Code changes to fix unobserved exception from getting thrown.

* Code changes to sync up with master and remvoe unnecessary changes.
  • Loading branch information
kundadebdatta authored Jan 31, 2024
1 parent d7a954f commit 83958bb
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
7 changes: 6 additions & 1 deletion Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,12 @@ private async Task RefreshDatabaseAccountInternalAsync(bool forceRefresh)
{
this.LastBackgroundRefreshUtc = DateTime.UtcNow;
this.locationCache.OnDatabaseAccountRead(await this.GetDatabaseAccountAsync(true));

}
catch (Exception ex)
{
DefaultTrace.TraceWarning("Failed to refresh database account with exception: {0}. Activity Id: '{1}'",
ex,
System.Diagnostics.Trace.CorrelationManager.ActivityId);
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,45 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync()
}
}

/// <summary>
/// Test to validate that when an exception is thrown during a RefreshLocationAsync call
/// the exception should not be bubbled up and remain unobserved. The exception should be
/// handled gracefully and logged as a warning trace event.
/// </summary>
[TestMethod]
public async Task RefreshLocationAsync_WhenGetDatabaseThrowsException_ShouldNotBubbleUpAsUnobservedException()
{
// Arrange.
Mock<IDocumentClientInternal> mockOwner = new Mock<IDocumentClientInternal>();
mockOwner.Setup(owner => owner.ServiceEndpoint).Returns(new Uri("https://defaultendpoint.net/"));
mockOwner.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny<Uri>(), It.IsAny<CancellationToken>())).ThrowsAsync(new TaskCanceledException());

//Create connection policy and populate preferred locations
ConnectionPolicy connectionPolicy = new ConnectionPolicy();
connectionPolicy.PreferredLocations.Add("ReadLocation1");
connectionPolicy.PreferredLocations.Add("ReadLocation2");

bool isExceptionLogged = false;
void TraceHandler(string message)
{
if (message.Contains("Failed to refresh database account with exception:"))
{
isExceptionLogged = true;
}
}

DefaultTrace.TraceSource.Listeners.Add(new TestTraceListener { Callback = TraceHandler });
DefaultTrace.InitEventListener();

using GlobalEndpointManager globalEndpointManager = new (mockOwner.Object, connectionPolicy);

// Act.
await globalEndpointManager.RefreshLocationAsync(forceRefresh: false);

// Assert.
Assert.IsTrue(isExceptionLogged, "The exception was logged as a warning trace event.");
}

private sealed class GetAccountRequestInjector
{
public Func<Uri, bool> ShouldFailRequest { get; set; }
Expand Down

0 comments on commit 83958bb

Please sign in to comment.