using Admin.NET.Plugin.AiDOP.Infrastructure;
using Admin.NET.Plugin.AiDOP.SmartOps;
using Furion.Schedule;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.Job;
///
/// 原子聚合表为空时(含 schema 修复后)自动构建四域全量历史原子 KPI,无需等待 hourly MDP。
///
[JobDetail("job_smart_ops_kpi_atomic_warmup", Description = "智慧运营KPI:原子层为空时自动预热(四域全量历史)", GroupName = "default", Concurrent = false)]
[PeriodSeconds(2, TriggerId = "trigger_smart_ops_kpi_atomic_warmup", Description = "启动后检测原子层并预热", MaxNumberOfRuns = 1, RunOnStart = true)]
public class SmartOpsKpiAtomicWarmupJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
public SmartOpsKpiAtomicWarmupJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
{
_scopeFactory = scopeFactory;
_logger = loggerFactory.CreateLogger(nameof(SmartOpsKpiAtomicWarmupJob));
}
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();
var build = scope.ServiceProvider.GetRequiredService();
try
{
AidopTenantMigration.EnsureKpiAtomicTable(db);
var rowCount = await db.Ado.GetIntAsync(
"SELECT COUNT(1) FROM ado_smart_ops_kpi_atomic_day WHERE is_deleted = 0");
if (rowCount > 0)
{
_logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 原子层已有 {RowCount} 行,跳过预热", rowCount);
return;
}
const string batchId = "ATOMIC_WARMUP";
var orderRows = await build.BuildOrderDeliveryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
var scheduleRows = await build.BuildWorkScheduleDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
var supplyRows = await build.BuildSupplyPurchaseDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
var inventoryRows = await build.BuildInventoryDomainForAllDatesAsync(batchId, cancellationToken: stoppingToken);
_logger.LogInformation(
"SmartOpsKpiAtomicWarmupJob: 预热完成 order={OrderRows} schedule={ScheduleRows} supply={SupplyRows} inventory={InventoryRows}",
orderRows, scheduleRows, supplyRows, inventoryRows);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("SmartOpsKpiAtomicWarmupJob: 收到停止信号");
throw;
}
catch (Exception ex)
{
_logger.LogError(ex, "SmartOpsKpiAtomicWarmupJob: 原子层预热失败");
}
}
}