47 lines
1.6 KiB
C#
47 lines
1.6 KiB
C#
using Microsoft.Extensions.Options;
|
|
|
|
namespace Nexus.Api.Services;
|
|
|
|
public sealed class StaleTaskRecoveryBackgroundService(
|
|
IServiceScopeFactory scopeFactory,
|
|
IOptionsMonitor<StaleTaskRecoveryOptions> optionsMonitor,
|
|
ILogger<StaleTaskRecoveryBackgroundService> logger) : BackgroundService
|
|
{
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
var resetCount = await RunRecoveryOnceAsync(stoppingToken);
|
|
if (resetCount > 0)
|
|
logger.LogInformation("Stale task recovery reset {ResetCount} task(s).", resetCount);
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogError(ex, "Stale task recovery run failed.");
|
|
}
|
|
|
|
try
|
|
{
|
|
await Task.Delay(optionsMonitor.CurrentValue.GetInterval(), stoppingToken);
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task<int> RunRecoveryOnceAsync(CancellationToken ct = default)
|
|
{
|
|
await using var scope = scopeFactory.CreateAsyncScope();
|
|
var recoveryService = scope.ServiceProvider.GetRequiredService<IStaleTaskRecoveryService>();
|
|
return await recoveryService.ResetStaleInProgressTasksAsync(optionsMonitor.CurrentValue.GetStaleThreshold(), ct);
|
|
}
|
|
}
|