diff --git a/src/IceRpc.Locator/Internal/LocationResolver.cs b/src/IceRpc.Locator/Internal/LocationResolver.cs
index 221213e01b..6947eaafae 100644
--- a/src/IceRpc.Locator/Internal/LocationResolver.cs
+++ b/src/IceRpc.Locator/Internal/LocationResolver.cs
@@ -29,6 +29,17 @@ internal static partial void LogFailedToResolve(
string locationKind,
Location location,
Exception? exception = null);
+
+ [LoggerMessage(
+ EventId = (int)LocationEventId.BackgroundRefreshFailed,
+ EventName = nameof(LocationEventId.BackgroundRefreshFailed),
+ Level = LogLevel.Debug,
+ Message = "Background cache refresh failed for {LocationKind} '{Location}'")]
+ internal static partial void LogBackgroundRefreshFailed(
+ this ILogger logger,
+ string locationKind,
+ Location location,
+ Exception exception);
}
/// An implementation of without a cache.
@@ -67,6 +78,7 @@ internal CacheLessLocationResolver(IServerAddressFinder serverAddressFinder) =>
internal class LocationResolver : ILocationResolver
{
private readonly bool _background;
+ private readonly ILogger _logger;
private readonly IServerAddressCache _serverAddressCache;
private readonly IServerAddressFinder _serverAddressFinder;
private readonly TimeSpan _refreshThreshold;
@@ -78,13 +90,15 @@ internal LocationResolver(
IServerAddressCache serverAddressCache,
bool background,
TimeSpan refreshThreshold,
- TimeSpan ttl)
+ TimeSpan ttl,
+ ILogger logger)
{
_serverAddressFinder = serverAddressFinder;
_serverAddressCache = serverAddressCache;
_background = background;
_refreshThreshold = refreshThreshold;
_ttl = ttl;
+ _logger = logger;
}
public ValueTask<(ServiceAddress? ServiceAddress, bool FromCache)> ResolveAsync(
@@ -118,7 +132,7 @@ internal LocationResolver(
else if (_background && expired)
{
// We retrieved an expired service address from the cache, so we launch a refresh in the background.
- _ = _serverAddressFinder.FindAsync(location, cancellationToken: default).ConfigureAwait(false);
+ _ = RefreshInBackgroundAsync();
}
// A well-known service address resolution can return a service address with an adapter-id.
@@ -150,6 +164,18 @@ internal LocationResolver(
}
return (serviceAddress, serviceAddress is not null && !resolved);
+
+ async Task RefreshInBackgroundAsync()
+ {
+ try
+ {
+ _ = await _serverAddressFinder.FindAsync(location, cancellationToken: default).ConfigureAwait(false);
+ }
+ catch (Exception exception)
+ {
+ _logger.LogBackgroundRefreshFailed(location.Kind, location, exception);
+ }
+ }
}
}
diff --git a/src/IceRpc.Locator/LocationEventId.cs b/src/IceRpc.Locator/LocationEventId.cs
index 7909439f68..7d69e47d30 100644
--- a/src/IceRpc.Locator/LocationEventId.cs
+++ b/src/IceRpc.Locator/LocationEventId.cs
@@ -25,5 +25,8 @@ public enum LocationEventId
FindFailed,
/// The server address finder found server address(es) for the given location.
- Found
+ Found,
+
+ /// A background cache refresh failed.
+ BackgroundRefreshFailed
}
diff --git a/src/IceRpc.Locator/LocatorInterceptor.cs b/src/IceRpc.Locator/LocatorInterceptor.cs
index ff8336d97a..5857035d8e 100644
--- a/src/IceRpc.Locator/LocatorInterceptor.cs
+++ b/src/IceRpc.Locator/LocatorInterceptor.cs
@@ -221,7 +221,8 @@ public LocatorLocationResolver(ILocator locator, LocatorOptions options, ILogger
serverAddressCache,
options.Background,
options.RefreshThreshold,
- options.Ttl);
+ options.Ttl,
+ logger);
if (logger != NullLogger.Instance)
{
_locationResolver = new LogLocationResolverDecorator(_locationResolver, logger);
diff --git a/tests/IceRpc.Locator.Tests/LocationResolverTests.cs b/tests/IceRpc.Locator.Tests/LocationResolverTests.cs
index d2e07e15d7..7b80042940 100644
--- a/tests/IceRpc.Locator.Tests/LocationResolverTests.cs
+++ b/tests/IceRpc.Locator.Tests/LocationResolverTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) ZeroC, Inc.
using IceRpc.Locator.Internal;
+using Microsoft.Extensions.Logging.Abstractions;
using NUnit.Framework;
namespace IceRpc.Locator.Tests;
@@ -21,7 +22,8 @@ public async Task ServerAddress_finder_not_called_when_cache_entry_age_is_less_o
new MockServerAddressCache(cachedServiceAddress, insertionTime: TimeSpan.FromSeconds(cacheEntryAge)),
background: false,
TimeSpan.FromSeconds(refreshThreshold),
- ttl: Timeout.InfiniteTimeSpan);
+ ttl: Timeout.InfiniteTimeSpan,
+ NullLogger.Instance);
(ServiceAddress? resolved, bool _) = await resolver.ResolveAsync(default, refreshCache: true, default);
@@ -44,7 +46,8 @@ public async Task ServerAddress_finder_called_when_cache_entry_age_is_greater_th
new MockServerAddressCache(cachedServiceAddress, insertionTime: TimeSpan.FromSeconds(cacheEntryAge)),
background: false,
TimeSpan.FromSeconds(refreshThreshold),
- ttl: Timeout.InfiniteTimeSpan);
+ ttl: Timeout.InfiniteTimeSpan,
+ NullLogger.Instance);
(ServiceAddress? resolved, bool _) = await resolver.ResolveAsync(default, refreshCache: true, default);
@@ -64,7 +67,8 @@ public async Task ServerAddress_finder_called_on_background()
new MockServerAddressCache(cachedServiceAddress, insertionTime: TimeSpan.FromSeconds(120)),
background: true,
TimeSpan.FromSeconds(1),
- ttl: TimeSpan.FromSeconds(30));
+ ttl: TimeSpan.FromSeconds(30),
+ NullLogger.Instance);
(ServiceAddress? resolved, bool fromCache) = await resolver.ResolveAsync(default, refreshCache: false, default);
@@ -84,7 +88,8 @@ public async Task Location_recursive_resolution()
new MockServerAddressCache(),
background: true,
TimeSpan.FromSeconds(1),
- ttl: TimeSpan.FromSeconds(30));
+ ttl: TimeSpan.FromSeconds(30),
+ NullLogger.Instance);
(ServiceAddress? resolved, bool fromCache) = await resolver.ResolveAsync(
new Location
@@ -111,7 +116,8 @@ public async Task Failure_to_recursively_resolve_adapter_id_removes_proxy_from_c
serverAddressCache,
background: true,
TimeSpan.FromSeconds(1),
- ttl: TimeSpan.FromSeconds(30));
+ ttl: TimeSpan.FromSeconds(30),
+ NullLogger.Instance);
var location = new Location
{
Value = "/hello",