MdpHotWatchWorker.cs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Hosting;
  3. using Microsoft.Extensions.Logging;
  4. namespace Admin.NET.Plugin.AiDOP.DataPlatform.HotWatch;
  5. /// <summary>热回读后台:默认每 5 秒一轮,Concurrent 由单实例循环保证不叠加。</summary>
  6. public sealed class MdpHotWatchWorker : BackgroundService
  7. {
  8. private static readonly TimeSpan Interval = TimeSpan.FromSeconds(5);
  9. private readonly IServiceScopeFactory _scopeFactory;
  10. private readonly ILogger _logger;
  11. public MdpHotWatchWorker(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
  12. {
  13. _scopeFactory = scopeFactory;
  14. _logger = loggerFactory.CreateLogger(nameof(MdpHotWatchWorker));
  15. }
  16. protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  17. {
  18. // 启动稍延后,避免与应用引导抢资源
  19. try { await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken); }
  20. catch (OperationCanceledException) { return; }
  21. // 非执行机直接退出整个轮询循环,而不是每轮空转——5 秒一拍的热回读是多实例下
  22. // 最密集的一条无效查询链路。配置在启动后不会变,求值一次即可。
  23. if (!AidopJobGate.ShouldRun(nameof(MdpHotWatchWorker), _logger)) return;
  24. while (!stoppingToken.IsCancellationRequested)
  25. {
  26. try
  27. {
  28. using var scope = _scopeFactory.CreateScope();
  29. var svc = scope.ServiceProvider.GetRequiredService<MdpHotWatchService>();
  30. var (polled, changed, terminated) = await svc.PollOnceAsync(100, stoppingToken);
  31. if (changed + terminated > 0)
  32. _logger.LogInformation(
  33. "[MdpHotWatchWorker] polled={Polled} changed={Changed} terminated={Terminated}",
  34. polled, changed, terminated);
  35. }
  36. catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
  37. {
  38. break;
  39. }
  40. catch (Exception ex)
  41. {
  42. _logger.LogWarning(ex, "[MdpHotWatchWorker] poll failed");
  43. }
  44. try { await Task.Delay(Interval, stoppingToken); }
  45. catch (OperationCanceledException) { break; }
  46. }
  47. }
  48. }