54 lines
2.0 KiB
C#
54 lines
2.0 KiB
C#
using MiaoJiZhang.Infrastructure.Persistence;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace MiaoJiZhang.Api.Services;
|
|
|
|
public class RecycleBinCleanupService(
|
|
IServiceScopeFactory scopeFactory,
|
|
ILogger<RecycleBinCleanupService> logger) : BackgroundService
|
|
{
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
await Cleanup(stoppingToken);
|
|
using var timer = new PeriodicTimer(TimeSpan.FromHours(24));
|
|
while (await timer.WaitForNextTickAsync(stoppingToken))
|
|
await Cleanup(stoppingToken);
|
|
}
|
|
|
|
private async Task Cleanup(CancellationToken ct)
|
|
{
|
|
try
|
|
{
|
|
using var scope = scopeFactory.CreateScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
var cutoff = DateTime.UtcNow.AddDays(-30);
|
|
var ids = await db.Transactions.IgnoreQueryFilters()
|
|
.Where(t => t.IsDeleted && t.DeletedAt < cutoff)
|
|
.Select(t => t.Id)
|
|
.ToListAsync(ct);
|
|
if (ids.Count == 0) return;
|
|
|
|
await db.ChatMessages
|
|
.Where(message =>
|
|
message.TransactionId.HasValue &&
|
|
ids.Contains(message.TransactionId.Value))
|
|
.ExecuteUpdateAsync(setters => setters
|
|
.SetProperty(message => message.TransactionId, (long?)null)
|
|
.SetProperty(message => message.Content, """{"deleted":true}"""), ct);
|
|
await db.Transactions.IgnoreQueryFilters()
|
|
.Where(t => ids.Contains(t.Id))
|
|
.ExecuteDeleteAsync(ct);
|
|
logger.LogInformation(
|
|
"Permanently removed {Count} transactions after recycle-bin retention",
|
|
ids.Count);
|
|
}
|
|
catch (OperationCanceledException) when (ct.IsCancellationRequested)
|
|
{
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.LogError(exception, "Recycle-bin cleanup failed");
|
|
}
|
|
}
|
|
}
|