using Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild; using Microsoft.Extensions.Logging; namespace Admin.NET.Plugin.AiDOP.DataPlatform.Inbound; /// /// 入站成功后按实体触发模块重建。映射为显式静态表;未登记实体记 Warning 不阻断接收。 /// public sealed class MdpInboundModuleTrigger : ITransient { // 方案 §7.7:MDM 不属任何单一模块,推送成功后触发所有依赖模块 private static readonly IReadOnlyDictionary EntityModuleMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["MDM_ITEM"] = ["S1", "S2", "S3", "S5", "S6"], ["MDM_CUSTOMER"] = ["S1"], ["MDM_SUPPLIER"] = ["S3", "S4", "S5"], ["MDM_SOURCE_LIST"] = ["S3"], ["MDM_LOCATION"] = ["S5", "S7"], ["MDM_EMPLOYEE_HEADCOUNT"] = ["S9"] }; private readonly ModuleRebuildService _rebuild; private readonly ILogger _logger; public MdpInboundModuleTrigger(ModuleRebuildService rebuild, ILogger logger) { _rebuild = rebuild; _logger = logger; } /// /// 任一模块 202 入队或 409 去抖视为已加急。异常不抛给接收方。 /// factoryId:Rebuild 要求 >0 且 ≠ tenantId,任务书字面 0 无法入队;grant 绑工厂优先生效,否则回落 1(与看板刷新一致)。 /// public async Task EnqueueForEntityAsync( string entityCode, long tenantId, long? grantFactoryId, CancellationToken ct) { var modules = ResolveModules(entityCode); if (modules.Count == 0) return false; var factoryId = ResolveFactoryId(tenantId, grantFactoryId); var enqueued = false; foreach (var module in modules) { if (string.Equals(module, "S9", StringComparison.OrdinalIgnoreCase)) { _logger.LogInformation("inbound trigger skip S9 (no rebuild handler) entity={Entity}", entityCode); continue; } if (!MdpRebuildScope.RebuildModules.Contains(module)) { _logger.LogWarning("inbound trigger skip unregistered module {Module} entity={Entity}", module, entityCode); continue; } try { var (status, body) = await _rebuild.EnqueueAsync( module, tenantId, factoryId, requestedBy: null, triggerType: "INBOUND", ct); if (status == 202) { enqueued = true; _logger.LogInformation( "inbound trigger queued module={Module} entity={Entity} job={Job} tenant={Tenant} factory={Factory}", module, entityCode, body.JobId, tenantId, factoryId); } else if (status == 409) { enqueued = true; _logger.LogInformation( "inbound trigger debounce module={Module} entity={Entity} status=409 {Message}", module, entityCode, body.Message); } else { _logger.LogWarning( "inbound trigger not accepted module={Module} entity={Entity} status={Status} {Message}", module, entityCode, status, body.Message); } } catch (Exception ex) { _logger.LogError(ex, "inbound trigger failed module={Module} entity={Entity}", module, entityCode); } } return enqueued; } private List ResolveModules(string entityCode) { if (string.IsNullOrWhiteSpace(entityCode)) return []; if (EntityModuleMap.TryGetValue(entityCode, out var mapped)) return mapped.ToList(); var prefix = entityCode.Trim(); var us = prefix.IndexOf('_'); if (us > 0) prefix = prefix[..us]; prefix = prefix.ToUpperInvariant(); if (MdpRebuildScope.RebuildModules.Contains(prefix)) return [prefix]; _logger.LogWarning("inbound trigger: entity {Entity} not in map and prefix {Prefix} is not a rebuild module", entityCode, prefix); return []; } private static long ResolveFactoryId(long tenantId, long? grantFactoryId) { if (grantFactoryId is > 0 && grantFactoryId.Value != tenantId) return grantFactoryId.Value; return 1; } }