MdpInboundModuleTrigger.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild;
  2. using Microsoft.Extensions.Logging;
  3. namespace Admin.NET.Plugin.AiDOP.DataPlatform.Inbound;
  4. /// <summary>
  5. /// 入站成功后按实体触发模块重建。映射为显式静态表;未登记实体记 Warning 不阻断接收。
  6. /// </summary>
  7. public sealed class MdpInboundModuleTrigger : ITransient
  8. {
  9. // 方案 §7.7:MDM 不属任何单一模块,推送成功后触发所有依赖模块
  10. private static readonly IReadOnlyDictionary<string, string[]> EntityModuleMap =
  11. new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
  12. {
  13. ["MDM_ITEM"] = ["S1", "S2", "S3", "S5", "S6"],
  14. ["MDM_CUSTOMER"] = ["S1"],
  15. ["MDM_SUPPLIER"] = ["S3", "S4", "S5"],
  16. ["MDM_SOURCE_LIST"] = ["S3"],
  17. ["MDM_LOCATION"] = ["S5", "S7"],
  18. ["MDM_EMPLOYEE_HEADCOUNT"] = ["S9"]
  19. };
  20. private readonly ModuleRebuildService _rebuild;
  21. private readonly ILogger<MdpInboundModuleTrigger> _logger;
  22. public MdpInboundModuleTrigger(ModuleRebuildService rebuild, ILogger<MdpInboundModuleTrigger> logger)
  23. {
  24. _rebuild = rebuild;
  25. _logger = logger;
  26. }
  27. /// <summary>
  28. /// 任一模块 202 入队或 409 去抖视为已加急。异常不抛给接收方。
  29. /// factoryId:Rebuild 要求 &gt;0 且 ≠ tenantId,任务书字面 0 无法入队;grant 绑工厂优先生效,否则回落 1(与看板刷新一致)。
  30. /// </summary>
  31. public async Task<bool> EnqueueForEntityAsync(
  32. string entityCode, long tenantId, long? grantFactoryId, CancellationToken ct)
  33. {
  34. var modules = ResolveModules(entityCode);
  35. if (modules.Count == 0)
  36. return false;
  37. var factoryId = ResolveFactoryId(tenantId, grantFactoryId);
  38. var enqueued = false;
  39. foreach (var module in modules)
  40. {
  41. if (string.Equals(module, "S9", StringComparison.OrdinalIgnoreCase))
  42. {
  43. _logger.LogInformation("inbound trigger skip S9 (no rebuild handler) entity={Entity}", entityCode);
  44. continue;
  45. }
  46. if (!MdpRebuildScope.RebuildModules.Contains(module))
  47. {
  48. _logger.LogWarning("inbound trigger skip unregistered module {Module} entity={Entity}", module, entityCode);
  49. continue;
  50. }
  51. try
  52. {
  53. var (status, body) = await _rebuild.EnqueueAsync(
  54. module, tenantId, factoryId, requestedBy: null, triggerType: "INBOUND", ct);
  55. if (status == 202)
  56. {
  57. enqueued = true;
  58. _logger.LogInformation(
  59. "inbound trigger queued module={Module} entity={Entity} job={Job} tenant={Tenant} factory={Factory}",
  60. module, entityCode, body.JobId, tenantId, factoryId);
  61. }
  62. else if (status == 409)
  63. {
  64. enqueued = true;
  65. _logger.LogInformation(
  66. "inbound trigger debounce module={Module} entity={Entity} status=409 {Message}",
  67. module, entityCode, body.Message);
  68. }
  69. else
  70. {
  71. _logger.LogWarning(
  72. "inbound trigger not accepted module={Module} entity={Entity} status={Status} {Message}",
  73. module, entityCode, status, body.Message);
  74. }
  75. }
  76. catch (Exception ex)
  77. {
  78. _logger.LogError(ex, "inbound trigger failed module={Module} entity={Entity}", module, entityCode);
  79. }
  80. }
  81. return enqueued;
  82. }
  83. private List<string> ResolveModules(string entityCode)
  84. {
  85. if (string.IsNullOrWhiteSpace(entityCode))
  86. return [];
  87. if (EntityModuleMap.TryGetValue(entityCode, out var mapped))
  88. return mapped.ToList();
  89. var prefix = entityCode.Trim();
  90. var us = prefix.IndexOf('_');
  91. if (us > 0)
  92. prefix = prefix[..us];
  93. prefix = prefix.ToUpperInvariant();
  94. if (MdpRebuildScope.RebuildModules.Contains(prefix))
  95. return [prefix];
  96. _logger.LogWarning("inbound trigger: entity {Entity} not in map and prefix {Prefix} is not a rebuild module",
  97. entityCode, prefix);
  98. return [];
  99. }
  100. private static long ResolveFactoryId(long tenantId, long? grantFactoryId)
  101. {
  102. if (grantFactoryId is > 0 && grantFactoryId.Value != tenantId)
  103. return grantFactoryId.Value;
  104. return 1;
  105. }
  106. }