wenxiangchao
4 天以前 559890c482f5973f06aafdfec9550fee5ba3c7f2
Aging.Infrastructure/InfrastructureBootstrapper.cs
@@ -1,5 +1,7 @@
using System.IO;
using log4net;
using HMI.Core.Util;
using Aging.Infrastructure.Broker;
using Aging.Infrastructure.Contracts;
using Aging.Infrastructure.Core;
using Aging.Infrastructure.Services;
@@ -32,10 +34,16 @@
            {
                log.Info("开始初始化基础设施服务...");
                // 1. 创建 ResourceManager 单例
                var resourceManager = new ResourceManager();
                // V3.0 MVP:仲裁库 arb.db(与 data.db 同目录)
                string arbPath = Path.Combine(Path.GetDirectoryName(deviceConfigDbPath)!, "arb.db");
                var leaseStore = new DbLeaseStore(arbPath, "local-main");
                // V3.0 INV-03:启动对账——上次进程异常退出未释放的租约在本机宿主更替后自动回收,
                // 避免调试/生产维护被 RecoveryRequired 永久阻塞(证据写入 recovery_checkpoint)
                leaseStore.ReconcileAfterBoot($"{Environment.MachineName}/{System.Diagnostics.Process.GetCurrentProcess().Id}");
                var resourceManager = new LayeredResourceManager(leaseStore);
                UtilContainer.RegisterUtil("LeaseCoordinator", leaseStore);
                UtilContainer.RegisterUtil("ResourceManager", resourceManager);
                log.Info("ResourceManager 已注册");
                log.Info("LayeredResourceManager (基于 DbLeaseStore) 已注册");
                // 2. 创建 DeviceManager 单例
                var deviceManager = new DeviceManager();
@@ -57,8 +65,21 @@
                UtilContainer.RegisterUtil("PowerSupplyService", powerSupplyService);
                log.Info("PowerSupplyService 已注册");
                // 6. 从数据库加载设备定义并注册驱动
                // 6. 创建 AutoDeviceFacade (自动化测试入口)
                var autoFacade = new AutoDeviceFacade(resourceManager, deviceService);
                UtilContainer.RegisterUtil("AutoDeviceFacade", autoFacade);
                log.Info("AutoDeviceFacade 已注册");
                // 7. 创建 CanBusService (CAN 类型化服务)
                var canBusService = new CanBusService(autoFacade);
                UtilContainer.RegisterUtil("CanBusService", canBusService);
                log.Info("CanBusService 已注册");
                // 8. 从数据库加载设备定义并注册驱动
                LoadDevicesFromConfig(deviceManager, mappingResolver);
                // 8.5. V3.0 混合架构:Broker 域设备注册代理驱动(物理会话由 DeviceBroker.exe 宿主唯一持有)
                RegisterBrokeredDrivers(deviceManager, deviceConfigDbPath);
                _initialized = true;
                log.Info("基础设施服务初始化完成");
@@ -71,6 +92,56 @@
        }
        /// <summary>
        /// V3.0:扫描配置库中 ExecutionMode=Broker 的设备,注册统一 CanDeviceDriver(BrokerRpc 代理后端)。
        /// Local 设备保持现有直驱路径不变;Broker 宿主未启动时代理仅在发起 I/O 时失败,不阻塞初始化。
        /// </summary>
        private static void RegisterBrokeredDrivers(IDeviceManager deviceManager, string deviceConfigDbPath)
        {
            try
            {
                if (!File.Exists(deviceConfigDbPath)) return;
                var brokeredDevices = new System.Collections.Generic.List<(string DeviceId, string BrokerId, string Endpoint)>();
                using (var conn = new System.Data.SQLite.SQLiteConnection(
                           $"Data Source={deviceConfigDbPath};Version=3;Read Only=True;"))
                {
                    conn.Open();
                    using var cmd = conn.CreateCommand();
                    cmd.CommandText = "SELECT DeviceId, BrokerId, Endpoint FROM DeviceDefinition WHERE ExecutionMode = 'Broker';";
                    using var rd = cmd.ExecuteReader();
                    while (rd.Read())
                    {
                        string id = rd.GetString(0);
                        string brokerId = rd.IsDBNull(1) ? "" : rd.GetString(1);
                        string endpoint = rd.IsDBNull(2) ? "" : rd.GetString(2);
                        if (!string.IsNullOrWhiteSpace(brokerId))
                            brokeredDevices.Add((id, brokerId, endpoint));
                    }
                }
                if (brokeredDevices.Count == 0) return;
                // INV-04:客户端侧生效配置快照,随每次 RPC 提交供 Broker 对账
                string configHash;
                try { configHash = DeviceConfigHash.Compute(deviceConfigDbPath); }
                catch { configHash = ""; }
                foreach (var (deviceId, brokerId, endpoint) in brokeredDevices)
                {
                    if (deviceManager.GetDriver(deviceId) != null) continue;
                    var driver = CanDeviceDriver.CreateBrokerProxy(deviceId, endpoint, BrokerPipeName.For(brokerId), configHash);
                    deviceManager.RegisterDriver(deviceId, driver);
                    log.Info($"[Bootstrapper] 设备 {deviceId} 已注册 Broker 代理驱动 (管道={BrokerPipeName.For(brokerId)}, hash={configHash.Substring(0, Math.Min(8, configHash.Length))})");
                }
            }
            catch (Exception ex)
            {
                // 代理注册失败降级:不影响 Local 直驱设备链路
                log.Warn($"[Bootstrapper] Broker 代理驱动注册失败(Broker 链路不可用,Local 设备不受影响): {ex.Message}", ex);
            }
        }
        /// <summary>
        /// 从 DeviceConfig 数据库加载设备定义并注册驱动
        /// </summary>
        private static void LoadDevicesFromConfig(IDeviceManager deviceManager, SlotDeviceMappingResolver mappingResolver)