SmartOpsKpiAtomicWarmupJob.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. using Admin.NET.Plugin.AiDOP.Infrastructure;
  2. using Admin.NET.Plugin.AiDOP.SmartOps;
  3. using Furion.Schedule;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.Extensions.Logging;
  6. using SqlSugar;
  7. namespace Admin.NET.Plugin.AiDOP.Job;
  8. /// <summary>
  9. /// 原子聚合表为空时(含 schema 修复后)自动构建四域全量历史原子 KPI,无需等待 hourly MDP。
  10. /// </summary>
  11. [JobDetail("job_smart_ops_kpi_atomic_warmup", Description = "智慧运营KPI:原子层为空时自动预热(四域全量历史)", GroupName = "default", Concurrent = false)]
  12. [PeriodSeconds(2, TriggerId = "trigger_smart_ops_kpi_atomic_warmup", Description = "启动后检测原子层并预热", MaxNumberOfRuns = 1, RunOnStart = true)]
  13. public class SmartOpsKpiAtomicWarmupJob : IJob
  14. {
  15. private readonly IServiceScopeFactory _scopeFactory;
  16. private readonly ILogger _logger;
  17. public SmartOpsKpiAtomicWarmupJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
  18. {
  19. _scopeFactory = scopeFactory;
  20. _logger = loggerFactory.CreateLogger(nameof(SmartOpsKpiAtomicWarmupJob));
  21. }
  22. public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
  23. {
  24. if (!AidopJobGate.ShouldRun(nameof(SmartOpsKpiAtomicWarmupJob), _logger)) return;
  25. using var scope = _scopeFactory.CreateScope();
  26. var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  27. var build = scope.ServiceProvider.GetRequiredService<SmartOpsKpiAtomicBuildService>();
  28. try
  29. {
  30. AidopTenantMigration.EnsureKpiAtomicTable(db);
  31. var rowCount = await db.Ado.GetIntAsync(
  32. "SELECT COUNT(1) FROM ado_smart_ops_kpi_atomic_day WHERE is_deleted = 0");
  33. if (rowCount > 0)
  34. {
  35. _logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 原子层已有 {RowCount} 行,跳过预热", rowCount);
  36. return;
  37. }
  38. const string batchId = "ATOMIC_WARMUP";
  39. var orderRows = await build.BuildOrderDeliveryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  40. var scheduleRows = await build.BuildWorkScheduleDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  41. var supplyRows = await build.BuildSupplyPurchaseDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  42. var inventoryRows = await build.BuildInventoryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  43. _logger.LogInformation(
  44. "SmartOpsKpiAtomicWarmupJob: 预热完成 order={OrderRows} schedule={ScheduleRows} supply={SupplyRows} inventory={InventoryRows}",
  45. orderRows, scheduleRows, supplyRows, inventoryRows);
  46. }
  47. catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
  48. {
  49. _logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 收到停止信号");
  50. throw;
  51. }
  52. catch (Exception ex)
  53. {
  54. _logger.LogError(ex, "SmartOpsKpiAtomicWarmupJob: 原子层预热失败");
  55. }
  56. }
  57. }