using Admin.NET.Plugin.AiDOP.MaterialWarehouse; using Furion.Schedule; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Admin.NET.Plugin.AiDOP.Job; /// S5 库存余额/流水冷链,每 30 分钟。跨实例锁由 InventoryMdpSyncService 持有。 [JobDetail("job_s5_inventory_inbound", Description = "S5库存余额/流水冷链,每30分钟", GroupName = "default", Concurrent = false)] [Cron("0,30 * * * *", TriggerId = "trigger_s5_inventory_inbound", Description = "每30分钟触发")] public sealed class S5InventoryInboundJob : IJob { private readonly IServiceScopeFactory _scopeFactory; private readonly ILogger _logger; public S5InventoryInboundJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory) { _scopeFactory = scopeFactory; _logger = loggerFactory.CreateLogger(nameof(S5InventoryInboundJob)); } public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { using var scope = _scopeFactory.CreateScope(); var sync = scope.ServiceProvider.GetRequiredService(); try { var result = await sync.RunIncrementalAsync(stoppingToken); _logger.LogInformation("[S5InventoryInboundJob] done skipped={Skipped} loc={Loc} trn={Trn}", result.Skipped, result.LocationPulled, result.TransPulled); } catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) { _logger.LogInformation("[S5InventoryInboundJob] cancelled"); throw; } catch (Exception ex) { _logger.LogError(ex, "[S5InventoryInboundJob] failed"); } } }