dotnet-cqrs/Svrnty.CQRS.Events/Services/ReadReceiptCleanupService.cs

89 lines
2.9 KiB
C#

using System;
using Svrnty.CQRS.Events.Configuration;
using Svrnty.CQRS.Events.Abstractions.Storage;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Svrnty.CQRS.Events.Abstractions;
namespace Svrnty.CQRS.Events.Services;
/// <summary>
/// Background service that periodically cleans up old read receipts.
/// </summary>
public class ReadReceiptCleanupService : BackgroundService
{
private readonly IReadReceiptStore _readReceiptStore;
private readonly ILogger<ReadReceiptCleanupService> _logger;
private readonly ReadReceiptOptions _options;
public ReadReceiptCleanupService(
IReadReceiptStore readReceiptStore,
ILogger<ReadReceiptCleanupService> logger,
IOptions<ReadReceiptOptions> options)
{
_readReceiptStore = readReceiptStore ?? throw new ArgumentNullException(nameof(readReceiptStore));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_options = options?.Value ?? throw new ArgumentNullException(nameof(options));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
if (!_options.EnableAutoCleanup)
{
_logger.LogInformation("Read receipt auto-cleanup is disabled");
return;
}
_logger.LogInformation(
"Read receipt cleanup service started (Interval: {Interval}, Retention: {Retention})",
_options.CleanupInterval,
_options.RetentionPeriod);
while (!stoppingToken.IsCancellationRequested)
{
try
{
await Task.Delay(_options.CleanupInterval, stoppingToken);
if (stoppingToken.IsCancellationRequested)
break;
await PerformCleanupAsync(stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
// Normal shutdown
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during read receipt cleanup");
// Continue running despite errors
}
}
_logger.LogInformation("Read receipt cleanup service stopped");
}
private async Task PerformCleanupAsync(CancellationToken cancellationToken)
{
var olderThan = DateTimeOffset.UtcNow.Subtract(_options.RetentionPeriod);
_logger.LogDebug("Starting read receipt cleanup (deleting receipts older than {OlderThan})", olderThan);
var deletedCount = await _readReceiptStore.CleanupAsync(olderThan, cancellationToken);
if (deletedCount > 0)
{
_logger.LogInformation("Cleaned up {DeletedCount} old read receipts", deletedCount);
}
else
{
_logger.LogDebug("No old read receipts to clean up");
}
}
}