Review 1.3: a routine discovery that could not be stored is not retried every 2 seconds

When saving a discovery failed in the repository (deadlock victim, lock timeout,
connection), LastDiscoveryAt stayed unset and the next round 2 seconds later
listed the same instance's databases again, loading the customer's server. The
agent now waits at least 15 minutes between routine discoveries of an instance.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Søren Eggert Lundsteen Olsen 2026-10-02 13:08:18 +02:00
parent f0c5d01294
commit a6a72661e7

View file

@ -41,6 +41,11 @@ public sealed partial class AgentRequestService(
public static readonly TimeSpan RequestTimeout = TimeSpan.FromMinutes(2);
/// <summary>The least time between two routine discoveries of one instance, also when the last one could not be stored.</summary>
public static readonly TimeSpan RoutineRetry = TimeSpan.FromMinutes(15);
private readonly Dictionary<int, DateTimeOffset> _routineAttempts = [];
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await readiness.Ready.WaitAsync(stoppingToken).ConfigureAwait(false);
@ -172,8 +177,11 @@ public sealed partial class AgentRequestService(
/// <summary>The routine discovery of the active instance that waited longest, if one is due.</summary>
private async Task RefreshOneAsync(DateTimeOffset now, CancellationToken cancellationToken)
{
// Also waits on the agent's own last attempt: if storing the result fails (the repository), LastDiscoveryAt is
// not set, and without this the same instance would be listed again every round (every 2 seconds).
var due = (await repository.GetConfiguredInstancesAsync(cancellationToken).ConfigureAwait(false))
.Where(i => !i.Paused && i.CredentialError is null && (i.LastDiscoveryAt is null || now.UtcDateTime - i.LastDiscoveryAt.Value >= DiscoveryInterval))
.Where(i => !_routineAttempts.TryGetValue(i.ConfiguredInstanceId, out var attempted) || now - attempted >= RoutineRetry)
.OrderBy(i => i.LastDiscoveryAt ?? DateTime.MinValue)
.FirstOrDefault();
if (due is null)
@ -181,6 +189,7 @@ public sealed partial class AgentRequestService(
return;
}
_routineAttempts[due.ConfiguredInstanceId] = now;
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
timeout.CancelAfter(RequestTimeout);
try