Files
jizhi/backend/MiaoJiZhang.Api/Services/RecycleBinCleanupService.cs
T
2026-07-24 23:11:20 +08:00

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");
}
}
}