From 48903bbf98e6292304a98b1b03207a2e50e20060 Mon Sep 17 00:00:00 2001 From: wxd <123@qq.com> Date: Thu, 27 Nov 2025 17:48:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuditLogs/CleanupInputDto.cs | 11 +++ .../CustomAuditLogCleanupAppService.cs | 90 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/Shentun.Peis.Application.Contracts/AuditLogs/CleanupInputDto.cs create mode 100644 src/Shentun.Peis.Application/AuditLogs/CustomAuditLogCleanupAppService.cs diff --git a/src/Shentun.Peis.Application.Contracts/AuditLogs/CleanupInputDto.cs b/src/Shentun.Peis.Application.Contracts/AuditLogs/CleanupInputDto.cs new file mode 100644 index 0000000..df69cfc --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/AuditLogs/CleanupInputDto.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.AuditLogs +{ + public class CleanupInputDto + { + public int retentionDays { get; set; } = 60; + } +} diff --git a/src/Shentun.Peis.Application/AuditLogs/CustomAuditLogCleanupAppService.cs b/src/Shentun.Peis.Application/AuditLogs/CustomAuditLogCleanupAppService.cs new file mode 100644 index 0000000..2502f44 --- /dev/null +++ b/src/Shentun.Peis.Application/AuditLogs/CustomAuditLogCleanupAppService.cs @@ -0,0 +1,90 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.AuditLogging; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Uow; + +namespace Shentun.Peis.AuditLogs +{ + /// + /// 清理日志 + /// + [ApiExplorerSettings(GroupName = "Work")] + [Authorize] + public class CustomAuditLogCleanupAppService : ITransientDependency + { + private readonly IRepository _auditLogRepository; + private readonly IRepository _auditLogActionRepository; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + public CustomAuditLogCleanupAppService( + IRepository auditLogRepository, + IRepository auditLogActionRepository, + IUnitOfWorkManager unitOfWorkManager) + { + _auditLogRepository = auditLogRepository; + _auditLogActionRepository = auditLogActionRepository; + _unitOfWorkManager = unitOfWorkManager; + } + + /// + /// 清理日志 + /// + /// + /// + [HttpPost("api/app/CustomAuditLogCleanup/Cleanup")] + public async Task CleanupAsync(CleanupInputDto input) + { + var cutoffTime = DateTime.Now.AddDays(-input.retentionDays); + + var hasMore = true; + var batchSize = 1000; + + while (hasMore) + { + using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) + { + // 1. 找到一批要删除的 AuditLog ID + var oldAuditLogIds = (await _auditLogRepository + .GetQueryableAsync()) + .Where(al => al.ExecutionTime < cutoffTime) + .Select(al => al.Id) + .Take(batchSize) + .ToList(); + + if (!oldAuditLogIds.Any()) + { + hasMore = false; + break; + } + + // 2. 删除关联的 AuditLogActions + var actionIdsToDelete = (await _auditLogActionRepository + .GetQueryableAsync()) + .Where(ala => oldAuditLogIds.Contains(ala.AuditLogId)) + .Select(ala => ala.Id) + .ToList(); + + if (actionIdsToDelete.Any()) + { + await _auditLogActionRepository.DeleteManyAsync(actionIdsToDelete); + } + + // 3. 删除 AuditLogs + await _auditLogRepository.DeleteManyAsync(oldAuditLogIds); + + await uow.CompleteAsync(); + } + + // 短暂延迟,减少数据库压力 + await Task.Delay(100); + } + } + } +}