using Microsoft.Extensions.Logging; using TakeoutSaaS.Domain.Finance.Repositories; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Module.Scheduler.Jobs; /// /// 经营报表快照刷新任务:消费排队中的报表快照并触发生成。 /// public sealed class FinanceBusinessReportRefreshJob( IFinanceBusinessReportRepository financeBusinessReportRepository, ITenantContextAccessor tenantContextAccessor, ILogger logger) { private const int BatchSize = 80; /// /// 执行报表快照刷新。 /// public async Task ExecuteAsync() { // 1. 拉取待处理快照任务。 var pendingList = await financeBusinessReportRepository.GetPendingSnapshotsAsync(BatchSize, CancellationToken.None); if (pendingList.Count == 0) { logger.LogDebug("定时任务:经营报表快照刷新无待处理任务"); return; } // 2. 逐租户上下文执行生成。 var successCount = 0; var failedCount = 0; foreach (var pending in pendingList) { var previousContext = tenantContextAccessor.Current; try { tenantContextAccessor.Current = new TenantContext( pending.TenantId, $"tenant-{pending.TenantId}", "scheduler"); await financeBusinessReportRepository.GenerateSnapshotAsync( pending.SnapshotId, CancellationToken.None); successCount += 1; } catch (Exception ex) { failedCount += 1; logger.LogError( ex, "定时任务:经营报表快照刷新失败 SnapshotId={SnapshotId}, TenantId={TenantId}", pending.SnapshotId, pending.TenantId); } finally { tenantContextAccessor.Current = previousContext; } } // 3. 记录执行结果。 logger.LogInformation( "定时任务:经营报表快照刷新完成,处理 {TotalCount} 条,成功 {SuccessCount} 条,失败 {FailedCount} 条", pendingList.Count, successCount, failedCount); } }