SmartOpsKpiAtomicWarmupJob.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. using var scope = _scopeFactory.CreateScope();
  25. var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  26. var build = scope.ServiceProvider.GetRequiredService<SmartOpsKpiAtomicBuildService>();
  27. try
  28. {
  29. AidopTenantMigration.EnsureKpiAtomicTable(db);
  30. var rowCount = await db.Ado.GetIntAsync(
  31. "SELECT COUNT(1) FROM ado_smart_ops_kpi_atomic_day WHERE is_deleted = 0");
  32. if (rowCount > 0)
  33. {
  34. _logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 原子层已有 {RowCount} 行,跳过预热", rowCount);
  35. return;
  36. }
  37. const string batchId = "ATOMIC_WARMUP";
  38. var orderRows = await build.BuildOrderDeliveryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  39. var scheduleRows = await build.BuildWorkScheduleDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  40. var supplyRows = await build.BuildSupplyPurchaseDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  41. var inventoryRows = await build.BuildInventoryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
  42. _logger.LogInformation(
  43. "SmartOpsKpiAtomicWarmupJob: 预热完成 order={OrderRows} schedule={ScheduleRows} supply={SupplyRows} inventory={InventoryRows}",
  44. orderRows, scheduleRows, supplyRows, inventoryRows);
  45. }
  46. catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
  47. {
  48. _logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 收到停止信号");
  49. throw;
  50. }
  51. catch (Exception ex)
  52. {
  53. _logger.LogError(ex, "SmartOpsKpiAtomicWarmupJob: 原子层预热失败");
  54. }
  55. }
  56. }