feat: implement notification system with repository, service, and controller layers
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using Distribution.Infra.UoW;
|
||||
|
||||
namespace Distribution.Features.Notifications;
|
||||
|
||||
/// <summary>
|
||||
/// Daily retention purge: deletes read inbox rows older than <c>Notifications:RetentionDays</c>
|
||||
/// (default 90), then any notification left with no recipients.
|
||||
/// </summary>
|
||||
public class NotificationCleanupJob(
|
||||
IServiceScopeFactory scopes,
|
||||
IConfiguration config,
|
||||
ILogger<NotificationCleanupJob> logger) : BackgroundService
|
||||
{
|
||||
private const int BatchSize = 500;
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
// Let the app finish starting before the first run.
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try { await RunOnceAsync(stoppingToken); }
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex) { logger.LogError(ex, "Notification cleanup failed."); }
|
||||
|
||||
await Task.Delay(TimeSpan.FromHours(24), stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunOnceAsync(CancellationToken ct)
|
||||
{
|
||||
var retentionDays = config.GetValue("Notifications:RetentionDays", 90);
|
||||
var cutoff = DateTime.Now.AddDays(-retentionDays);
|
||||
|
||||
using var scope = scopes.CreateScope();
|
||||
var repo = scope.ServiceProvider.GetRequiredService<INotificationRepository>();
|
||||
var uow = scope.ServiceProvider.GetRequiredService<IUnitOfWork>();
|
||||
|
||||
var removed = 0;
|
||||
while (true)
|
||||
{
|
||||
var expired = await repo.GetExpiredReadRecipientsAsync(cutoff, BatchSize);
|
||||
if (expired.Count == 0) break;
|
||||
|
||||
repo.RemoveRecipients(expired);
|
||||
await uow.CommitAsync(ct);
|
||||
removed += expired.Count;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
var orphans = await repo.GetOrphanNotificationsAsync(BatchSize);
|
||||
if (orphans.Count == 0) break;
|
||||
|
||||
repo.RemoveNotifications(orphans);
|
||||
await uow.CommitAsync(ct);
|
||||
}
|
||||
|
||||
if (removed > 0)
|
||||
logger.LogInformation("Notification cleanup removed {Count} read inbox rows older than {Days} days.", removed, retentionDays);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user