MdpConfiguredDbSyncJob.cs 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using System.Text.Json;
  2. using Admin.NET.Plugin.AiDOP.DataPlatform;
  3. using Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild;
  4. using Admin.NET.Plugin.AiDOP.Entity.DataPlatform;
  5. using Furion.Schedule;
  6. using Microsoft.Extensions.DependencyInjection;
  7. using Microsoft.Extensions.Logging;
  8. namespace Admin.NET.Plugin.AiDOP.Job;
  9. /// <summary>
  10. /// 方式甲动态调度。不标注 JobDetail,避免被内置扫描当成固定作业删掉。
  11. /// </summary>
  12. public sealed class MdpConfiguredDbSyncJob : IJob
  13. {
  14. private readonly IServiceScopeFactory _scopeFactory;
  15. private readonly ILogger _logger;
  16. public MdpConfiguredDbSyncJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
  17. {
  18. _scopeFactory = scopeFactory;
  19. _logger = loggerFactory.CreateLogger(nameof(MdpConfiguredDbSyncJob));
  20. }
  21. public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
  22. {
  23. var payload = JsonSerializer.Deserialize<Payload>(context.JobDetail.Properties ?? "{}");
  24. if (payload == null || payload.TenantId <= 0 || string.IsNullOrWhiteSpace(payload.TaskCode))
  25. {
  26. _logger.LogWarning("方式甲调度缺少 tenantId 或 taskCode");
  27. return;
  28. }
  29. using var scope = _scopeFactory.CreateScope();
  30. var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  31. var ops = scope.ServiceProvider.GetRequiredService<MdpDbEntityOperationService>();
  32. var neutralProjection = scope.ServiceProvider.GetRequiredService<MdpDbSyncNeutralProjection>();
  33. var rebuild = scope.ServiceProvider.GetRequiredService<MdpDbSyncRebuildTrigger>();
  34. var task = await db.Queryable<MdpSyncTask>()
  35. .Where(x => x.TaskCode == payload.TaskCode && x.TenantId == payload.TenantId && x.Status == 1)
  36. .FirstAsync(stoppingToken);
  37. if (task == null || !string.Equals(task.TaskType, "DB_SYNC", StringComparison.OrdinalIgnoreCase))
  38. return;
  39. var schedule = await db.Queryable<MdpSyncTaskSchedule>()
  40. .Where(x => x.TaskCode == task.TaskCode && x.TenantId == task.TenantId)
  41. .FirstAsync(stoppingToken);
  42. if (schedule == null || schedule.AutoEnabled != 1)
  43. return;
  44. var entities = await db.Queryable<MdpEntity>()
  45. .Where(x => x.Status == 1 && (x.TenantId == payload.TenantId || x.TenantId == 0))
  46. .Where(x => x.JobId == task.TaskCode || x.JobId == task.JobCode)
  47. .ToListAsync(stoppingToken);
  48. var failed = 0;
  49. foreach (var entity in entities)
  50. {
  51. stoppingToken.ThrowIfCancellationRequested();
  52. var issues = MdpDbSyncRules.ValidateDbEntity(entity, "DB");
  53. if (issues.Count > 0)
  54. {
  55. failed++;
  56. continue;
  57. }
  58. try
  59. {
  60. var mode = string.IsNullOrWhiteSpace(schedule.SyncWindowType) ? entity.SyncMode : schedule.SyncWindowType;
  61. await ops.RunEntityAsync(entity.Id, mode, "调度自动执行", "AUTO", stoppingToken, payload.TenantId);
  62. }
  63. catch (Exception ex)
  64. {
  65. failed++;
  66. _logger.LogError(ex, "方式甲实体 {EntityCode} 调度失败", entity.EntityCode);
  67. }
  68. }
  69. if (failed > 0)
  70. {
  71. _logger.LogWarning("方式甲任务 {TaskCode} 有 {Failed} 个实体未成功", task.TaskCode, failed);
  72. throw new InvalidOperationException(
  73. $"方式甲任务 {task.TaskCode} 有 {failed} 个实体未成功,本轮不触发模块重算");
  74. }
  75. else if (entities.Count > 0)
  76. {
  77. await neutralProjection.ProjectAsync(entities, payload.TenantId, stoppingToken);
  78. var modules = await rebuild.EnqueueForTaskAsync(
  79. task, payload.TenantId, factoryId: 1, triggerType: ModuleRebuildTriggerType.DbSync, stoppingToken);
  80. _logger.LogInformation(
  81. "方式甲任务 {TaskCode} 抽取完成,已触发模块重算:{Modules}",
  82. task.TaskCode,
  83. modules.Count == 0 ? "无" : string.Join(",", modules));
  84. }
  85. }
  86. private sealed class Payload
  87. {
  88. public long TenantId { get; set; }
  89. public string? TaskCode { get; set; }
  90. }
  91. }