electron-infra-kit 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +302 -0
- package/README.zh-CN.md +308 -0
- package/dist/core/error/WindowError.d.ts +56 -0
- package/dist/core/error/WindowError.js +71 -0
- package/dist/core/error/WindowError.js.map +1 -0
- package/dist/core/error/WindowError.mjs +71 -0
- package/dist/core/error/WindowError.mjs.map +1 -0
- package/dist/core/ipc/IpcHandler.d.ts +48 -0
- package/dist/core/ipc/IpcHandler.js +59 -0
- package/dist/core/ipc/IpcHandler.js.map +1 -0
- package/dist/core/ipc/IpcHandler.mjs +59 -0
- package/dist/core/ipc/IpcHandler.mjs.map +1 -0
- package/dist/core/ipc/IpcRouter.d.ts +70 -0
- package/dist/core/ipc/IpcRouter.js +143 -0
- package/dist/core/ipc/IpcRouter.js.map +1 -0
- package/dist/core/ipc/IpcRouter.mjs +143 -0
- package/dist/core/ipc/IpcRouter.mjs.map +1 -0
- package/dist/core/ipc/index.d.ts +3 -0
- package/dist/core/ipc/index.js +1 -0
- package/dist/core/ipc/index.js.map +1 -0
- package/dist/core/ipc/index.mjs +1 -0
- package/dist/core/ipc/index.mjs.map +1 -0
- package/dist/core/ipc/ipc-router.type.d.ts +73 -0
- package/dist/core/ipc/transport/index.d.ts +65 -0
- package/dist/core/ipc/transport/index.js +229 -0
- package/dist/core/ipc/transport/index.js.map +1 -0
- package/dist/core/ipc/transport/index.mjs +229 -0
- package/dist/core/ipc/transport/index.mjs.map +1 -0
- package/dist/core/ipc/transport/ipc.type.d.ts +36 -0
- package/dist/core/lifecycle/LifecycleManager.d.ts +66 -0
- package/dist/core/lifecycle/LifecycleManager.js +140 -0
- package/dist/core/lifecycle/LifecycleManager.js.map +1 -0
- package/dist/core/lifecycle/LifecycleManager.mjs +140 -0
- package/dist/core/lifecycle/LifecycleManager.mjs.map +1 -0
- package/dist/core/message-bus/MessageBus.d.ts +282 -0
- package/dist/core/message-bus/MessageBus.js +677 -0
- package/dist/core/message-bus/MessageBus.js.map +1 -0
- package/dist/core/message-bus/MessageBus.mjs +677 -0
- package/dist/core/message-bus/MessageBus.mjs.map +1 -0
- package/dist/core/message-bus/MessageBusClient.d.ts +100 -0
- package/dist/core/message-bus/MessageBusClient.js +280 -0
- package/dist/core/message-bus/MessageBusClient.js.map +1 -0
- package/dist/core/message-bus/MessageBusClient.mjs +280 -0
- package/dist/core/message-bus/MessageBusClient.mjs.map +1 -0
- package/dist/core/message-bus/core/DataStoreManager.d.ts +51 -0
- package/dist/core/message-bus/core/DataStoreManager.js +94 -0
- package/dist/core/message-bus/core/DataStoreManager.js.map +1 -0
- package/dist/core/message-bus/core/DataStoreManager.mjs +94 -0
- package/dist/core/message-bus/core/DataStoreManager.mjs.map +1 -0
- package/dist/core/message-bus/core/ManagedPort.d.ts +26 -0
- package/dist/core/message-bus/core/ManagedPort.js +55 -0
- package/dist/core/message-bus/core/ManagedPort.js.map +1 -0
- package/dist/core/message-bus/core/ManagedPort.mjs +55 -0
- package/dist/core/message-bus/core/ManagedPort.mjs.map +1 -0
- package/dist/core/message-bus/core/PortManager.d.ts +47 -0
- package/dist/core/message-bus/core/PortManager.js +114 -0
- package/dist/core/message-bus/core/PortManager.js.map +1 -0
- package/dist/core/message-bus/core/PortManager.mjs +114 -0
- package/dist/core/message-bus/core/PortManager.mjs.map +1 -0
- package/dist/core/message-bus/core/SubscriptionManager.d.ts +36 -0
- package/dist/core/message-bus/core/SubscriptionManager.js +78 -0
- package/dist/core/message-bus/core/SubscriptionManager.js.map +1 -0
- package/dist/core/message-bus/core/SubscriptionManager.mjs +78 -0
- package/dist/core/message-bus/core/SubscriptionManager.mjs.map +1 -0
- package/dist/core/message-bus/core/TransactionManager.d.ts +54 -0
- package/dist/core/message-bus/core/TransactionManager.js +95 -0
- package/dist/core/message-bus/core/TransactionManager.js.map +1 -0
- package/dist/core/message-bus/core/TransactionManager.mjs +95 -0
- package/dist/core/message-bus/core/TransactionManager.mjs.map +1 -0
- package/dist/core/message-bus/core/index.d.ts +5 -0
- package/dist/core/message-bus/index.d.ts +4 -0
- package/dist/core/message-bus/index.js +1 -0
- package/dist/core/message-bus/index.js.map +1 -0
- package/dist/core/message-bus/index.mjs +1 -0
- package/dist/core/message-bus/index.mjs.map +1 -0
- package/dist/core/message-bus/message-bus.type.d.ts +143 -0
- package/dist/core/message-bus/message-bus.type.js +26 -0
- package/dist/core/message-bus/message-bus.type.js.map +1 -0
- package/dist/core/message-bus/message-bus.type.mjs +26 -0
- package/dist/core/message-bus/message-bus.type.mjs.map +1 -0
- package/dist/core/message-bus/preload.d.ts +16 -0
- package/dist/core/message-bus/preload.js +27 -0
- package/dist/core/message-bus/preload.js.map +1 -0
- package/dist/core/message-bus/preload.mjs +27 -0
- package/dist/core/message-bus/preload.mjs.map +1 -0
- package/dist/core/message-bus/transport/ITransport.d.ts +40 -0
- package/dist/core/message-bus/transport/IpcTransport.d.ts +18 -0
- package/dist/core/message-bus/transport/IpcTransport.js +60 -0
- package/dist/core/message-bus/transport/IpcTransport.js.map +1 -0
- package/dist/core/message-bus/transport/IpcTransport.mjs +60 -0
- package/dist/core/message-bus/transport/IpcTransport.mjs.map +1 -0
- package/dist/core/message-bus/transport/MessagePortTransport.d.ts +15 -0
- package/dist/core/message-bus/transport/MessagePortTransport.js +35 -0
- package/dist/core/message-bus/transport/MessagePortTransport.js.map +1 -0
- package/dist/core/message-bus/transport/MessagePortTransport.mjs +35 -0
- package/dist/core/message-bus/transport/MessagePortTransport.mjs.map +1 -0
- package/dist/core/message-bus/transport/index.d.ts +3 -0
- package/dist/core/window/IpcSetup.d.ts +50 -0
- package/dist/core/window/IpcSetup.js +96 -0
- package/dist/core/window/IpcSetup.js.map +1 -0
- package/dist/core/window/IpcSetup.mjs +96 -0
- package/dist/core/window/IpcSetup.mjs.map +1 -0
- package/dist/core/window/WindowCreator.d.ts +66 -0
- package/dist/core/window/WindowCreator.js +168 -0
- package/dist/core/window/WindowCreator.js.map +1 -0
- package/dist/core/window/WindowCreator.mjs +168 -0
- package/dist/core/window/WindowCreator.mjs.map +1 -0
- package/dist/core/window/WindowManager.d.ts +214 -0
- package/dist/core/window/WindowManager.js +583 -0
- package/dist/core/window/WindowManager.js.map +1 -0
- package/dist/core/window/WindowManager.mjs +583 -0
- package/dist/core/window/WindowManager.mjs.map +1 -0
- package/dist/core/window/WindowStore.d.ts +136 -0
- package/dist/core/window/WindowStore.js +436 -0
- package/dist/core/window/WindowStore.js.map +1 -0
- package/dist/core/window/WindowStore.mjs +436 -0
- package/dist/core/window/WindowStore.mjs.map +1 -0
- package/dist/core/window/constants.d.ts +17 -0
- package/dist/core/window/constants.js +15 -0
- package/dist/core/window/constants.js.map +1 -0
- package/dist/core/window/constants.mjs +15 -0
- package/dist/core/window/constants.mjs.map +1 -0
- package/dist/core/window/core/MetricsManager.d.ts +14 -0
- package/dist/core/window/core/MetricsManager.js +27 -0
- package/dist/core/window/core/MetricsManager.js.map +1 -0
- package/dist/core/window/core/MetricsManager.mjs +27 -0
- package/dist/core/window/core/MetricsManager.mjs.map +1 -0
- package/dist/core/window/core/PluginExecutor.d.ts +22 -0
- package/dist/core/window/core/PluginExecutor.js +110 -0
- package/dist/core/window/core/PluginExecutor.js.map +1 -0
- package/dist/core/window/core/PluginExecutor.mjs +110 -0
- package/dist/core/window/core/PluginExecutor.mjs.map +1 -0
- package/dist/core/window/core/WindowContextManager.d.ts +26 -0
- package/dist/core/window/core/WindowContextManager.js +59 -0
- package/dist/core/window/core/WindowContextManager.js.map +1 -0
- package/dist/core/window/core/WindowContextManager.mjs +59 -0
- package/dist/core/window/core/WindowContextManager.mjs.map +1 -0
- package/dist/core/window/core/WindowLifecycle.d.ts +15 -0
- package/dist/core/window/core/WindowLifecycle.js +150 -0
- package/dist/core/window/core/WindowLifecycle.js.map +1 -0
- package/dist/core/window/core/WindowLifecycle.mjs +150 -0
- package/dist/core/window/core/WindowLifecycle.mjs.map +1 -0
- package/dist/core/window/core/WindowOperator.d.ts +90 -0
- package/dist/core/window/core/WindowOperator.js +154 -0
- package/dist/core/window/core/WindowOperator.js.map +1 -0
- package/dist/core/window/core/WindowOperator.mjs +154 -0
- package/dist/core/window/core/WindowOperator.mjs.map +1 -0
- package/dist/core/window/core/WindowRegistry.d.ts +168 -0
- package/dist/core/window/core/WindowRegistry.js +331 -0
- package/dist/core/window/core/WindowRegistry.js.map +1 -0
- package/dist/core/window/core/WindowRegistry.mjs +331 -0
- package/dist/core/window/core/WindowRegistry.mjs.map +1 -0
- package/dist/core/window/core/WindowStateManager.d.ts +40 -0
- package/dist/core/window/core/WindowStateManager.js +110 -0
- package/dist/core/window/core/WindowStateManager.js.map +1 -0
- package/dist/core/window/core/WindowStateManager.mjs +110 -0
- package/dist/core/window/core/WindowStateManager.mjs.map +1 -0
- package/dist/core/window/index.d.ts +7 -0
- package/dist/core/window/index.js +1 -0
- package/dist/core/window/index.js.map +1 -0
- package/dist/core/window/index.mjs +1 -0
- package/dist/core/window/index.mjs.map +1 -0
- package/dist/core/window/window-manager.schema.d.ts +50 -0
- package/dist/core/window/window-manager.schema.js +87 -0
- package/dist/core/window/window-manager.schema.js.map +1 -0
- package/dist/core/window/window-manager.schema.mjs +87 -0
- package/dist/core/window/window-manager.schema.mjs.map +1 -0
- package/dist/core/window/window-manager.type.d.ts +365 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +33 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1 -0
- package/dist/infrastructure/config/ConfigManager.d.ts +133 -0
- package/dist/infrastructure/config/ConfigManager.js +218 -0
- package/dist/infrastructure/config/ConfigManager.js.map +1 -0
- package/dist/infrastructure/config/ConfigManager.mjs +218 -0
- package/dist/infrastructure/config/ConfigManager.mjs.map +1 -0
- package/dist/infrastructure/config/index.d.ts +1 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.d.ts +106 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.js +218 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.js.map +1 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.mjs +218 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.mjs.map +1 -0
- package/dist/infrastructure/debug/PerformanceMonitor.d.ts +45 -0
- package/dist/infrastructure/debug/PerformanceMonitor.js +67 -0
- package/dist/infrastructure/debug/PerformanceMonitor.js.map +1 -0
- package/dist/infrastructure/debug/PerformanceMonitor.mjs +67 -0
- package/dist/infrastructure/debug/PerformanceMonitor.mjs.map +1 -0
- package/dist/infrastructure/debug/index.d.ts +22 -0
- package/dist/infrastructure/debug/index.js +47 -0
- package/dist/infrastructure/debug/index.js.map +1 -0
- package/dist/infrastructure/debug/index.mjs +47 -0
- package/dist/infrastructure/debug/index.mjs.map +1 -0
- package/dist/infrastructure/errors/ErrorCodes.d.ts +74 -0
- package/dist/infrastructure/errors/ErrorCodes.js +78 -0
- package/dist/infrastructure/errors/ErrorCodes.js.map +1 -0
- package/dist/infrastructure/errors/ErrorCodes.mjs +78 -0
- package/dist/infrastructure/errors/ErrorCodes.mjs.map +1 -0
- package/dist/infrastructure/errors/StandardError.d.ts +61 -0
- package/dist/infrastructure/errors/StandardError.js +84 -0
- package/dist/infrastructure/errors/StandardError.js.map +1 -0
- package/dist/infrastructure/errors/StandardError.mjs +84 -0
- package/dist/infrastructure/errors/StandardError.mjs.map +1 -0
- package/dist/infrastructure/errors/index.d.ts +13 -0
- package/dist/infrastructure/errors/index.js +24 -0
- package/dist/infrastructure/errors/index.js.map +1 -0
- package/dist/infrastructure/errors/index.mjs +24 -0
- package/dist/infrastructure/errors/index.mjs.map +1 -0
- package/dist/infrastructure/logger/ElectronLogger.d.ts +39 -0
- package/dist/infrastructure/logger/ElectronLogger.js +65 -0
- package/dist/infrastructure/logger/ElectronLogger.js.map +1 -0
- package/dist/infrastructure/logger/ElectronLogger.mjs +65 -0
- package/dist/infrastructure/logger/ElectronLogger.mjs.map +1 -0
- package/dist/infrastructure/logger/index.d.ts +2 -0
- package/dist/infrastructure/logger/logger.type.d.ts +8 -0
- package/dist/internal/types/BrandedTypes.d.ts +64 -0
- package/dist/internal/types/BrandedTypes.js +54 -0
- package/dist/internal/types/BrandedTypes.js.map +1 -0
- package/dist/internal/types/BrandedTypes.mjs +54 -0
- package/dist/internal/types/BrandedTypes.mjs.map +1 -0
- package/dist/internal/types/PerformanceOptions.d.ts +87 -0
- package/dist/internal/types/branded.d.ts +42 -0
- package/dist/internal/utils/MessageDispatcher.d.ts +67 -0
- package/dist/internal/utils/MessageDispatcher.js +96 -0
- package/dist/internal/utils/MessageDispatcher.js.map +1 -0
- package/dist/internal/utils/MessageDispatcher.mjs +96 -0
- package/dist/internal/utils/MessageDispatcher.mjs.map +1 -0
- package/dist/internal/utils/RateLimiter.d.ts +41 -0
- package/dist/internal/utils/RateLimiter.js +83 -0
- package/dist/internal/utils/RateLimiter.js.map +1 -0
- package/dist/internal/utils/RateLimiter.mjs +83 -0
- package/dist/internal/utils/RateLimiter.mjs.map +1 -0
- package/dist/internal/utils/StateKeeper.d.ts +125 -0
- package/dist/internal/utils/StateKeeper.js +334 -0
- package/dist/internal/utils/StateKeeper.js.map +1 -0
- package/dist/internal/utils/StateKeeper.mjs +334 -0
- package/dist/internal/utils/StateKeeper.mjs.map +1 -0
- package/dist/internal/utils/branded-helpers.d.ts +33 -0
- package/dist/internal/utils/index.d.ts +5 -0
- package/dist/preload/index.d.ts +45 -0
- package/dist/preload/index.js +91 -0
- package/dist/preload/index.js.map +1 -0
- package/dist/preload/index.mjs +91 -0
- package/dist/preload/index.mjs.map +1 -0
- package/dist/preload/preload.type.d.ts +15 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +1 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
'use strict';var electron=require('electron'),events=require('events'),MessageDispatcher=require('../../internal/utils/MessageDispatcher.js'),messageBus_type=require('./message-bus.type.js'),constants=require('../window/constants.js'),TransactionManager=require('./core/TransactionManager.js'),SubscriptionManager=require('./core/SubscriptionManager.js'),DataStoreManager=require('./core/DataStoreManager.js'),ElectronLogger=require('../../infrastructure/logger/ElectronLogger.js'),IpcTransport=require('./transport/IpcTransport.js'),MessagePortTransport=require('./transport/MessagePortTransport.js'),PerformanceMonitor=require('../../infrastructure/debug/PerformanceMonitor.js');/**
|
|
2
|
+
* MessageBus - Multi-window state synchronization and communication bridge
|
|
3
|
+
* MessageBus - 多窗口状态同步与通信桥梁
|
|
4
|
+
*
|
|
5
|
+
* Design patterns / 设计模式:
|
|
6
|
+
* - Shared State (Instance-based): Singleton instance holds shared state (单例实例持有共享状态)
|
|
7
|
+
* - Transport Layer Abstraction: Decouples communication mechanism (传输层抽象:解耦通信机制)
|
|
8
|
+
* - Permission Control: Field-level + Window-level dual permission (权限控制:字段级 + 窗口级双重权限)
|
|
9
|
+
* - Message Proxy: Unified communication interface (消息代理:统一的通信接口)
|
|
10
|
+
* - Componentized: Delegates responsibilities to core managers (组件化:将职责委托给核心管理器)
|
|
11
|
+
*/
|
|
12
|
+
class MessageBus extends events.EventEmitter {
|
|
13
|
+
eventName = constants.EVENTS.WINDOW_STATE_CHANGED;
|
|
14
|
+
logger;
|
|
15
|
+
// Core Managers
|
|
16
|
+
// 核心管理器
|
|
17
|
+
subscriptionManager;
|
|
18
|
+
transactionManager;
|
|
19
|
+
dataStoreManager;
|
|
20
|
+
// Transport Layer
|
|
21
|
+
// 传输层
|
|
22
|
+
transport;
|
|
23
|
+
transportMode;
|
|
24
|
+
windows = new Map();
|
|
25
|
+
// Message dispatcher
|
|
26
|
+
// 消息分发器
|
|
27
|
+
dispatcher;
|
|
28
|
+
// Group resolver for P2P messaging
|
|
29
|
+
// P2P 消息的分组解析器
|
|
30
|
+
groupResolver;
|
|
31
|
+
// Track watch callbacks for cleanup
|
|
32
|
+
// 跟踪 watch 回调以便清理
|
|
33
|
+
watchCallbacks = new Set();
|
|
34
|
+
// Window subscriptions for auto cleanup (Task 1)
|
|
35
|
+
// 窗口订阅用于自动清理 (任务 1)
|
|
36
|
+
windowSubscriptions = new WeakMap();
|
|
37
|
+
/**
|
|
38
|
+
* Create a new MessageBus instance
|
|
39
|
+
* 创建一个新的 MessageBus 实例
|
|
40
|
+
*
|
|
41
|
+
* @param options - Configuration options
|
|
42
|
+
*/
|
|
43
|
+
constructor(options = {}) {
|
|
44
|
+
super();
|
|
45
|
+
this.eventName = options.eventName || constants.EVENTS.WINDOW_STATE_CHANGED;
|
|
46
|
+
this.logger = options.logger || new ElectronLogger.ElectronLogger({ appName: 'MessageBus' });
|
|
47
|
+
this.dispatcher = new MessageDispatcher.MessageDispatcher('MessageBus', this.logger);
|
|
48
|
+
this.subscriptionManager = new SubscriptionManager.SubscriptionManager(this.logger);
|
|
49
|
+
this.transactionManager = new TransactionManager.TransactionManager(this.logger);
|
|
50
|
+
this.dataStoreManager = new DataStoreManager.DataStoreManager();
|
|
51
|
+
// Initialize Transport Strategy (Task 5)
|
|
52
|
+
// 初始化传输策略 (任务 5)
|
|
53
|
+
const mode = options.transportMode || 'auto';
|
|
54
|
+
this.transportMode = this.selectTransportMode(mode);
|
|
55
|
+
this.transport = this.createTransport(this.transportMode);
|
|
56
|
+
try {
|
|
57
|
+
this.transport.init((msg, windowId) => this.handleTransportMessage(msg, windowId));
|
|
58
|
+
this.logger.info(`MessageBus initialized with ${this.transportMode} transport`);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// Fallback if initialization fails
|
|
62
|
+
this.logger.error(`Failed to initialize ${this.transportMode} transport: ${error}. Falling back to IPC.`);
|
|
63
|
+
this.transportMode = 'ipc';
|
|
64
|
+
this.transport = new IpcTransport.IpcTransport(this.logger);
|
|
65
|
+
this.transport.init((msg, windowId) => this.handleTransportMessage(msg, windowId));
|
|
66
|
+
}
|
|
67
|
+
this.registerDefaultHandlers();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Select transport mode
|
|
71
|
+
* 选择传输模式
|
|
72
|
+
*/
|
|
73
|
+
selectTransportMode(mode) {
|
|
74
|
+
if (mode === 'ipc')
|
|
75
|
+
return 'ipc';
|
|
76
|
+
if (mode === 'messageport')
|
|
77
|
+
return 'messageport';
|
|
78
|
+
// Auto: Check environment capabilities
|
|
79
|
+
// 自动:检查环境能力
|
|
80
|
+
if (typeof electron.MessageChannelMain === 'undefined') {
|
|
81
|
+
this.logger.warn('MessageChannelMain not available, falling back to IPC transport');
|
|
82
|
+
return 'ipc';
|
|
83
|
+
}
|
|
84
|
+
return 'messageport';
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create transport instance
|
|
88
|
+
* 创建传输实例
|
|
89
|
+
*/
|
|
90
|
+
createTransport(mode) {
|
|
91
|
+
if (mode === 'ipc')
|
|
92
|
+
return new IpcTransport.IpcTransport(this.logger);
|
|
93
|
+
return new MessagePortTransport.MessagePortTransport(this.logger);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Handle incoming message from transport
|
|
97
|
+
* 处理来自传输层的消息
|
|
98
|
+
*/
|
|
99
|
+
handleTransportMessage(msg, windowId) {
|
|
100
|
+
try {
|
|
101
|
+
if (msg && msg.type) {
|
|
102
|
+
const result = this.dispatcher.dispatch(msg.type, this, { ...msg, windowId });
|
|
103
|
+
// Handle response if requestId exists (for 'get' requests)
|
|
104
|
+
if (msg.requestId) {
|
|
105
|
+
Promise.resolve(result)
|
|
106
|
+
.then((value) => {
|
|
107
|
+
this.transport.send(windowId, {
|
|
108
|
+
type: messageBus_type.MessageProtocolType.GET_RESPONSE,
|
|
109
|
+
requestId: msg.requestId,
|
|
110
|
+
value,
|
|
111
|
+
});
|
|
112
|
+
})
|
|
113
|
+
.catch((err) => {
|
|
114
|
+
this.logger.error(`Error handling message ${msg.type}: ${err}`);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
this.logger.error(`Failed to handle message from window ${windowId}: ${error}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Register a window with MessageBus
|
|
125
|
+
* 注册窗口到 MessageBus
|
|
126
|
+
* @param windowId - Window ID (窗口 ID)
|
|
127
|
+
* @param window - BrowserWindow instance (BrowserWindow 实例)
|
|
128
|
+
*/
|
|
129
|
+
registerWindow(windowId, window) {
|
|
130
|
+
// Clean up existing registration if any
|
|
131
|
+
// 清理现有的注册(如果有)
|
|
132
|
+
this.unregisterWindow(windowId);
|
|
133
|
+
this.windows.set(windowId, window);
|
|
134
|
+
this.transport.registerWindow(windowId, window);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Unregister a window from MessageBus
|
|
138
|
+
* 从 MessageBus 注销窗口
|
|
139
|
+
* @param windowId - Window ID (窗口 ID)
|
|
140
|
+
*/
|
|
141
|
+
unregisterWindow(windowId) {
|
|
142
|
+
// 1. Clean up window-specific subscriptions (Task 1)
|
|
143
|
+
const window = this.windows.get(windowId);
|
|
144
|
+
if (window && this.windowSubscriptions.has(window)) {
|
|
145
|
+
const unsubs = this.windowSubscriptions.get(window);
|
|
146
|
+
if (unsubs) {
|
|
147
|
+
this.logger.info(`Cleaning up ${unsubs.size} subscriptions for window ${windowId}`);
|
|
148
|
+
unsubs.forEach((unsub) => {
|
|
149
|
+
try {
|
|
150
|
+
unsub();
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
/* ignore */
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
this.windowSubscriptions.delete(window);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.transport.unregisterWindow(windowId);
|
|
160
|
+
this.windows.delete(windowId);
|
|
161
|
+
// Remove subscriptions for this window
|
|
162
|
+
// 移除该窗口的订阅
|
|
163
|
+
this.subscriptionManager.removeWindow(windowId);
|
|
164
|
+
// Rollback any active transactions
|
|
165
|
+
// 回滚任何活跃事务
|
|
166
|
+
if (this.transactionManager.hasTransaction(windowId)) {
|
|
167
|
+
this.transactionManager.rollback(windowId);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Auto register/unregister windows with WindowManager
|
|
172
|
+
* 自动注册/注销窗口与 WindowManager
|
|
173
|
+
* @param windowManager - WindowManager instance (WindowManager 实例)
|
|
174
|
+
*/
|
|
175
|
+
autoRegisterWindows(windowManager) {
|
|
176
|
+
// Register on window creation
|
|
177
|
+
// 在窗口创建时注册
|
|
178
|
+
windowManager.on('window-created', ({ window, id }) => {
|
|
179
|
+
this.registerWindow(id, window);
|
|
180
|
+
});
|
|
181
|
+
// Unregister on window destruction
|
|
182
|
+
// 在窗口销毁时注销
|
|
183
|
+
windowManager.on('window-will-be-destroyed', (id) => {
|
|
184
|
+
this.unregisterWindow(id);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Dispose all resources
|
|
189
|
+
* 释放所有资源
|
|
190
|
+
*/
|
|
191
|
+
dispose() {
|
|
192
|
+
this.logger.info('Disposing MessageBus...');
|
|
193
|
+
// 1. Clean up all watch callbacks
|
|
194
|
+
// 清理所有 watch 回调
|
|
195
|
+
this.watchCallbacks.forEach((unsubscribe) => {
|
|
196
|
+
try {
|
|
197
|
+
unsubscribe();
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
this.logger.warn(`Failed to unsubscribe watch callback: ${error}`);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
this.watchCallbacks.clear();
|
|
204
|
+
// 2. Clean up MessageHandlers
|
|
205
|
+
this.dispatcher.clear();
|
|
206
|
+
// 3. Dispose transport
|
|
207
|
+
this.transport.dispose();
|
|
208
|
+
// 4. Clear data and subscriptions
|
|
209
|
+
this.dataStoreManager.clear();
|
|
210
|
+
this.subscriptionManager.clear();
|
|
211
|
+
this.transactionManager.clear();
|
|
212
|
+
this.windows.clear();
|
|
213
|
+
// 5. Remove all event listeners
|
|
214
|
+
this.removeAllListeners();
|
|
215
|
+
this.logger.info('MessageBus disposed');
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Register a single event handler
|
|
219
|
+
* 注册单个事件处理器
|
|
220
|
+
* @param handler - Event handler (事件处理器)
|
|
221
|
+
*/
|
|
222
|
+
registerHandler(handler) {
|
|
223
|
+
this.on(handler.eventName, handler.callback);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Batch register event handlers
|
|
227
|
+
* 批量注册事件处理器
|
|
228
|
+
* @param handlers - Array of event handlers (事件处理器数组)
|
|
229
|
+
*/
|
|
230
|
+
registerHandlers(handlers) {
|
|
231
|
+
handlers.forEach((handler) => this.registerHandler(handler));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Unregister a single event handler
|
|
235
|
+
* 注销单个事件处理器
|
|
236
|
+
* @param handler - Event handler (事件处理器)
|
|
237
|
+
*/
|
|
238
|
+
unregisterHandler(handler) {
|
|
239
|
+
this.removeListener(handler.eventName, handler.callback);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Batch unregister event handlers
|
|
243
|
+
* 批量注销事件处理器
|
|
244
|
+
* @param handlers - Array of event handlers (事件处理器数组)
|
|
245
|
+
*/
|
|
246
|
+
unregisterHandlers(handlers) {
|
|
247
|
+
handlers.forEach((handler) => this.unregisterHandler(handler));
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get data
|
|
251
|
+
* 获取数据
|
|
252
|
+
* @param key - Data key, returns all data if not provided (数据键,不传则返回所有数据)
|
|
253
|
+
* @returns Data value or all data (数据值或所有数据)
|
|
254
|
+
*/
|
|
255
|
+
getData(key) {
|
|
256
|
+
if (key) {
|
|
257
|
+
return this.dataStoreManager.get(key);
|
|
258
|
+
}
|
|
259
|
+
return this.dataStoreManager.getAll();
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Check permission
|
|
263
|
+
* 检查权限
|
|
264
|
+
* @param key - Data key (数据键)
|
|
265
|
+
* @param windowId - Operation window ID (操作窗口 ID)
|
|
266
|
+
* @param operation - Operation type (操作类型)
|
|
267
|
+
* @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
|
|
268
|
+
*/
|
|
269
|
+
checkPermission(key, windowId, operation) {
|
|
270
|
+
return this.dataStoreManager.checkPermission(key, windowId, operation);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Set data (with permission check and transaction support)
|
|
274
|
+
* 设置数据(带权限验证和事务支持)
|
|
275
|
+
* @param key - Data key (数据键)
|
|
276
|
+
* @param value - Data value (数据值)
|
|
277
|
+
* @param windowId - Operation window ID (操作窗口 ID)
|
|
278
|
+
* @param eventName - Optional event name (可选的事件名称)
|
|
279
|
+
* @param skipTransaction - Whether to skip transaction check (是否跳过事务检查)
|
|
280
|
+
* @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
|
|
281
|
+
*/
|
|
282
|
+
setData(key, value, windowId, eventName, skipTransaction = false) {
|
|
283
|
+
const permissionCheck = this.checkPermission(key, windowId, 'modify');
|
|
284
|
+
if (!permissionCheck.success) {
|
|
285
|
+
return permissionCheck;
|
|
286
|
+
}
|
|
287
|
+
// Handle Transaction
|
|
288
|
+
if (!skipTransaction && windowId && this.transactionManager.hasTransaction(windowId)) {
|
|
289
|
+
this.transactionManager.add(windowId, key, { type: 'set', value });
|
|
290
|
+
return { success: true };
|
|
291
|
+
}
|
|
292
|
+
const item = this.dataStoreManager.getItem(key);
|
|
293
|
+
const oldValue = item?.value;
|
|
294
|
+
this.dataStoreManager.set(key, value);
|
|
295
|
+
// Broadcast change
|
|
296
|
+
// 广播变更
|
|
297
|
+
const event = {
|
|
298
|
+
type: messageBus_type.MessageProtocolType.SET,
|
|
299
|
+
key,
|
|
300
|
+
value,
|
|
301
|
+
oldValue,
|
|
302
|
+
windowId,
|
|
303
|
+
timestamp: Date.now(),
|
|
304
|
+
};
|
|
305
|
+
this.broadcastChange(event);
|
|
306
|
+
this.emit(eventName || this.eventName, event);
|
|
307
|
+
return { success: true };
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Delete data
|
|
311
|
+
* 删除数据
|
|
312
|
+
* @param key - Data key (数据键)
|
|
313
|
+
* @param windowId - Operation window ID (操作窗口 ID)
|
|
314
|
+
* @param eventName - Optional event name (可选的事件名称)
|
|
315
|
+
* @param skipTransaction - Whether to skip transaction check (是否跳过事务检查)
|
|
316
|
+
* @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
|
|
317
|
+
*/
|
|
318
|
+
deleteData(key, windowId, eventName, skipTransaction = false) {
|
|
319
|
+
const permissionCheck = this.checkPermission(key, windowId, 'delete');
|
|
320
|
+
if (!permissionCheck.success) {
|
|
321
|
+
return permissionCheck;
|
|
322
|
+
}
|
|
323
|
+
// Handle Transaction
|
|
324
|
+
if (!skipTransaction && windowId && this.transactionManager.hasTransaction(windowId)) {
|
|
325
|
+
this.transactionManager.add(windowId, key, { type: 'delete' });
|
|
326
|
+
return { success: true };
|
|
327
|
+
}
|
|
328
|
+
const item = this.dataStoreManager.getItem(key);
|
|
329
|
+
const oldValue = item?.value;
|
|
330
|
+
this.dataStoreManager.delete(key);
|
|
331
|
+
const event = {
|
|
332
|
+
type: messageBus_type.MessageProtocolType.DELETE,
|
|
333
|
+
key,
|
|
334
|
+
oldValue,
|
|
335
|
+
windowId,
|
|
336
|
+
timestamp: Date.now(),
|
|
337
|
+
};
|
|
338
|
+
this.broadcastChange(event);
|
|
339
|
+
this.emit(eventName || this.eventName, event);
|
|
340
|
+
return { success: true };
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Start a transaction
|
|
344
|
+
* 开启事务
|
|
345
|
+
* @param windowId - Window ID (窗口 ID)
|
|
346
|
+
*/
|
|
347
|
+
startTransaction(windowId) {
|
|
348
|
+
this.transactionManager.start(windowId);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Commit a transaction
|
|
352
|
+
* 提交事务
|
|
353
|
+
* @param windowId - Window ID (窗口 ID)
|
|
354
|
+
*/
|
|
355
|
+
commitTransaction(windowId) {
|
|
356
|
+
const buffer = this.transactionManager.commit(windowId);
|
|
357
|
+
if (!buffer)
|
|
358
|
+
return;
|
|
359
|
+
buffer.forEach((op, key) => {
|
|
360
|
+
if (op.type === 'set') {
|
|
361
|
+
this.setData(key, op.value, windowId, undefined, true);
|
|
362
|
+
}
|
|
363
|
+
else if (op.type === 'delete') {
|
|
364
|
+
this.deleteData(key, windowId, undefined, true);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Rollback a transaction
|
|
370
|
+
* 回滚事务
|
|
371
|
+
* @param windowId - Window ID (窗口 ID)
|
|
372
|
+
*/
|
|
373
|
+
rollbackTransaction(windowId) {
|
|
374
|
+
this.transactionManager.rollback(windowId);
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Watch for data changes (Main Process)
|
|
378
|
+
* 监听数据变化(主进程)
|
|
379
|
+
*
|
|
380
|
+
* ⚠️ IMPORTANT: You must call the returned unsubscribe function to prevent memory leaks
|
|
381
|
+
* ⚠️ 重要:必须调用返回的取消订阅函数以防止内存泄漏
|
|
382
|
+
*
|
|
383
|
+
* @param key - Data key to watch (监听的键)
|
|
384
|
+
* @param callback - Callback function (回调函数)
|
|
385
|
+
* @param windowId - Optional window ID to bind lifecycle (可选的窗口 ID,用于绑定生命周期)
|
|
386
|
+
* @returns Unsubscribe function (取消订阅函数)
|
|
387
|
+
*/
|
|
388
|
+
watch(key, callback, windowId) {
|
|
389
|
+
const handler = (event) => {
|
|
390
|
+
if ('key' in event && event.key === key) {
|
|
391
|
+
if (event.type === messageBus_type.MessageProtocolType.SET) {
|
|
392
|
+
callback(event.value, event.oldValue);
|
|
393
|
+
}
|
|
394
|
+
else if (event.type === messageBus_type.MessageProtocolType.DELETE) {
|
|
395
|
+
callback(undefined, event.oldValue);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
this.on(this.eventName, handler);
|
|
400
|
+
const unsubscribe = () => {
|
|
401
|
+
this.off(this.eventName, handler);
|
|
402
|
+
this.watchCallbacks.delete(unsubscribe);
|
|
403
|
+
// Cleanup from weak map if exists
|
|
404
|
+
if (windowId) {
|
|
405
|
+
const window = this.windows.get(windowId);
|
|
406
|
+
if (window && this.windowSubscriptions.has(window)) {
|
|
407
|
+
this.windowSubscriptions.get(window)?.delete(unsubscribe);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
// Track for automatic cleanup on dispose
|
|
412
|
+
// 跟踪以便在 dispose 时自动清理
|
|
413
|
+
this.watchCallbacks.add(unsubscribe);
|
|
414
|
+
// Track for window lifecycle cleanup (Task 1)
|
|
415
|
+
if (windowId) {
|
|
416
|
+
const window = this.windows.get(windowId);
|
|
417
|
+
if (window) {
|
|
418
|
+
if (!this.windowSubscriptions.has(window)) {
|
|
419
|
+
this.windowSubscriptions.set(window, new Set());
|
|
420
|
+
}
|
|
421
|
+
this.windowSubscriptions.get(window).add(unsubscribe);
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
this.logger.warn(`Window ${windowId} not found, watch subscription will not be auto-cleaned up on window destroy`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return unsubscribe;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Atomic update
|
|
431
|
+
* 原子更新
|
|
432
|
+
* @param key - Data key (数据键)
|
|
433
|
+
* @param updater - Updater function or new value (更新函数或新值)
|
|
434
|
+
* @param windowId - Window ID (窗口 ID)
|
|
435
|
+
*/
|
|
436
|
+
updateData(key, updater, windowId) {
|
|
437
|
+
let currentValue = this.dataStoreManager.get(key);
|
|
438
|
+
if (windowId) {
|
|
439
|
+
const buffered = this.transactionManager.getBufferedValue(windowId, key);
|
|
440
|
+
if (buffered.has) {
|
|
441
|
+
currentValue = buffered.value;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const newValue = typeof updater === 'function' ? updater(currentValue) : updater;
|
|
445
|
+
return this.setData(key, newValue, windowId);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Set field permission
|
|
449
|
+
* 设置字段权限
|
|
450
|
+
* @param key - Data key (数据键)
|
|
451
|
+
* @param permission - Permission object (权限对象)
|
|
452
|
+
*/
|
|
453
|
+
setFieldPermission(key, permission) {
|
|
454
|
+
this.dataStoreManager.setPermission(key, permission);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get registered windows list (for debugging)
|
|
458
|
+
* 获取已注册的窗口列表(调试用)
|
|
459
|
+
* @returns Array of registered window IDs (已注册的窗口 ID 数组)
|
|
460
|
+
*/
|
|
461
|
+
getRegisteredWindows() {
|
|
462
|
+
return Array.from(this.windows.keys());
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Register message handler
|
|
466
|
+
* 注册消息处理器
|
|
467
|
+
* @param handler - Bus message handler (总线消息处理器)
|
|
468
|
+
*/
|
|
469
|
+
registerMessageHandler(handler) {
|
|
470
|
+
this.dispatcher.register(handler.name, handler.callback);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Register default handlers
|
|
474
|
+
* 注册默认处理器
|
|
475
|
+
*/
|
|
476
|
+
registerDefaultHandlers() {
|
|
477
|
+
this.registerMessageHandler({
|
|
478
|
+
name: messageBus_type.MessageProtocolType.GET,
|
|
479
|
+
callback: (bus, { key } = {}) => bus.getData(key),
|
|
480
|
+
});
|
|
481
|
+
this.registerMessageHandler({
|
|
482
|
+
name: messageBus_type.MessageProtocolType.SET,
|
|
483
|
+
callback: (bus, { key, value, windowId, eventName }) => bus.setData(key, value, windowId, eventName),
|
|
484
|
+
});
|
|
485
|
+
this.registerMessageHandler({
|
|
486
|
+
name: messageBus_type.MessageProtocolType.DELETE,
|
|
487
|
+
callback: (bus, { key, windowId, eventName }) => bus.deleteData(key, windowId, eventName),
|
|
488
|
+
});
|
|
489
|
+
this.registerMessageHandler({
|
|
490
|
+
name: messageBus_type.MessageProtocolType.SET_PERMISSION,
|
|
491
|
+
callback: (bus, { key, permission }) => bus.setFieldPermission(key, permission),
|
|
492
|
+
});
|
|
493
|
+
this.registerMessageHandler({
|
|
494
|
+
name: messageBus_type.MessageProtocolType.SUBSCRIBE,
|
|
495
|
+
callback: (bus, { windowId, keys }) => bus.subscribe(windowId, keys),
|
|
496
|
+
});
|
|
497
|
+
this.registerMessageHandler({
|
|
498
|
+
name: messageBus_type.MessageProtocolType.UNSUBSCRIBE,
|
|
499
|
+
callback: (bus, { windowId, keys }) => bus.unsubscribe(windowId, keys),
|
|
500
|
+
});
|
|
501
|
+
this.registerMessageHandler({
|
|
502
|
+
name: messageBus_type.MessageProtocolType.TRANSACTION_START,
|
|
503
|
+
callback: (bus, { windowId }) => bus.startTransaction(windowId),
|
|
504
|
+
});
|
|
505
|
+
this.registerMessageHandler({
|
|
506
|
+
name: messageBus_type.MessageProtocolType.TRANSACTION_COMMIT,
|
|
507
|
+
callback: (bus, { windowId }) => bus.commitTransaction(windowId),
|
|
508
|
+
});
|
|
509
|
+
this.registerMessageHandler({
|
|
510
|
+
name: messageBus_type.MessageProtocolType.TRANSACTION_ROLLBACK,
|
|
511
|
+
callback: (bus, { windowId }) => bus.rollbackTransaction(windowId),
|
|
512
|
+
});
|
|
513
|
+
this.registerMessageHandler({
|
|
514
|
+
name: messageBus_type.MessageProtocolType.SEND_TO_WINDOW,
|
|
515
|
+
callback: (bus, { targetWindowId, channel, data }) => bus.sendToWindow(targetWindowId, channel, data),
|
|
516
|
+
});
|
|
517
|
+
this.registerMessageHandler({
|
|
518
|
+
name: messageBus_type.MessageProtocolType.SEND_TO_GROUP,
|
|
519
|
+
callback: (bus, { group, channel, data }) => bus.sendToGroup(group, channel, data),
|
|
520
|
+
});
|
|
521
|
+
this.registerMessageHandler({
|
|
522
|
+
name: messageBus_type.MessageProtocolType.UPDATE,
|
|
523
|
+
callback: (bus, { key, value, windowId }) => {
|
|
524
|
+
return bus.setData(key, value, windowId);
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Handle message
|
|
530
|
+
* 处理消息
|
|
531
|
+
* @param name - Message name (消息名称)
|
|
532
|
+
* @param data - Message data (消息数据)
|
|
533
|
+
* @returns Result of handler (处理器结果)
|
|
534
|
+
*/
|
|
535
|
+
handleMessage(name, data) {
|
|
536
|
+
return this.dispatcher.dispatch(name, this, data);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Initialize communication listener (optional)
|
|
540
|
+
* 初始化通信监听器(可选)
|
|
541
|
+
*
|
|
542
|
+
* Allows renderer process to read/write data directly via unified channel.
|
|
543
|
+
* 允许渲染进程通过统一通道直接读写数据。
|
|
544
|
+
*/
|
|
545
|
+
initializeListener() {
|
|
546
|
+
// Unified channel, optimize communication
|
|
547
|
+
// 统一通道,优化通信方式
|
|
548
|
+
electron.ipcMain.handle('message-bus-invoke', (_, { name, data }) => this.handleMessage(name, data));
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Set group resolver
|
|
552
|
+
* 设置分组解析器
|
|
553
|
+
* @param resolver - Group resolver function (分组解析函数)
|
|
554
|
+
*/
|
|
555
|
+
setGroupResolver(resolver) {
|
|
556
|
+
this.groupResolver = resolver;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Send message to specific window
|
|
560
|
+
* 发送消息到指定窗口
|
|
561
|
+
* @param windowId - Target window ID (目标窗口 ID)
|
|
562
|
+
* @param channel - Channel name (频道名称)
|
|
563
|
+
* @param data - Message data (消息数据)
|
|
564
|
+
* @returns Success or not (是否成功)
|
|
565
|
+
*/
|
|
566
|
+
sendToWindow(windowId, channel, data) {
|
|
567
|
+
const perf = PerformanceMonitor.PerformanceMonitor.getInstance();
|
|
568
|
+
const measureId = `message-bus-send-${Date.now()}`;
|
|
569
|
+
perf.startMeasure(measureId, 'MessageBus Send', { windowId, channel });
|
|
570
|
+
if (!this.windows.has(windowId)) {
|
|
571
|
+
this.logger.warn(`Window ${windowId} not found or not registered`);
|
|
572
|
+
perf.endMeasure(measureId, { status: 'failed', reason: 'window_not_found' });
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
const message = {
|
|
577
|
+
type: messageBus_type.MessageProtocolType.MESSAGE,
|
|
578
|
+
channel,
|
|
579
|
+
value: data,
|
|
580
|
+
timestamp: Date.now(),
|
|
581
|
+
};
|
|
582
|
+
this.transport.send(windowId, JSON.stringify(message));
|
|
583
|
+
perf.endMeasure(measureId, { status: 'success' });
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
this.logger.error(`Failed to send message to window ${windowId}: ${error}`);
|
|
588
|
+
this.emit('error', error);
|
|
589
|
+
perf.endMeasure(measureId, {
|
|
590
|
+
status: 'error',
|
|
591
|
+
error: error instanceof Error ? error.message : String(error),
|
|
592
|
+
});
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Send message to a group of windows
|
|
598
|
+
* 发送消息到一组窗口
|
|
599
|
+
* @param group - Group name (组名)
|
|
600
|
+
* @param channel - Channel name (频道名称)
|
|
601
|
+
* @param data - Message data (消息数据)
|
|
602
|
+
* @returns Number of successful sends (成功发送的数量)
|
|
603
|
+
*/
|
|
604
|
+
sendToGroup(group, channel, data) {
|
|
605
|
+
const perf = PerformanceMonitor.PerformanceMonitor.getInstance();
|
|
606
|
+
const measureId = `message-bus-broadcast-${Date.now()}`;
|
|
607
|
+
perf.startMeasure(measureId, 'MessageBus Broadcast', { group, channel });
|
|
608
|
+
if (!this.groupResolver) {
|
|
609
|
+
this.logger.warn('Group resolver not set, cannot send to group');
|
|
610
|
+
perf.endMeasure(measureId, { status: 'failed', reason: 'no_group_resolver' });
|
|
611
|
+
return 0;
|
|
612
|
+
}
|
|
613
|
+
const windowIds = this.groupResolver(group);
|
|
614
|
+
const count = this.broadcastToWindows(windowIds, channel, data);
|
|
615
|
+
perf.endMeasure(measureId, {
|
|
616
|
+
status: 'success',
|
|
617
|
+
windowCount: windowIds.length,
|
|
618
|
+
successCount: count,
|
|
619
|
+
});
|
|
620
|
+
return count;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Broadcast message to specific windows
|
|
624
|
+
* 广播消息到指定的一组窗口
|
|
625
|
+
* @param windowIds - Target window IDs (目标窗口 ID 列表)
|
|
626
|
+
* @param channel - Channel name (频道名称)
|
|
627
|
+
* @param data - Message data (消息数据)
|
|
628
|
+
* @returns Number of successful sends (成功发送的数量)
|
|
629
|
+
*/
|
|
630
|
+
broadcastToWindows(windowIds, channel, data) {
|
|
631
|
+
const message = {
|
|
632
|
+
type: messageBus_type.MessageProtocolType.MESSAGE,
|
|
633
|
+
channel,
|
|
634
|
+
value: data,
|
|
635
|
+
timestamp: Date.now(),
|
|
636
|
+
};
|
|
637
|
+
const serializedMessage = JSON.stringify(message);
|
|
638
|
+
return this.transport.broadcast(serializedMessage, windowIds);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Subscribe to specific keys
|
|
642
|
+
* 订阅特定的 key
|
|
643
|
+
* @param windowId - Window ID (窗口 ID)
|
|
644
|
+
* @param keys - Keys to subscribe (订阅的 key 列表)
|
|
645
|
+
*/
|
|
646
|
+
subscribe(windowId, keys) {
|
|
647
|
+
this.subscriptionManager.subscribe(windowId, keys);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Unsubscribe from specific keys
|
|
651
|
+
* 取消订阅特定的 key
|
|
652
|
+
* @param windowId - Window ID (窗口 ID)
|
|
653
|
+
* @param keys - Keys to unsubscribe (取消订阅的 key 列表)
|
|
654
|
+
*/
|
|
655
|
+
unsubscribe(windowId, keys) {
|
|
656
|
+
this.subscriptionManager.unsubscribe(windowId, keys);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Broadcast changes to all windows via Transport
|
|
660
|
+
* 通过传输层广播变更到所有窗口
|
|
661
|
+
* @param event - Data change event (数据变更事件)
|
|
662
|
+
*/
|
|
663
|
+
broadcastChange(event) {
|
|
664
|
+
const message = JSON.stringify(event);
|
|
665
|
+
// If it's a key-based event and has subscribers, only broadcast to them
|
|
666
|
+
// 如果是基于 key 的事件且有订阅者,只广播给订阅者
|
|
667
|
+
if ('key' in event && event.key) {
|
|
668
|
+
const subscribers = this.subscriptionManager.getSubscribers(event.key);
|
|
669
|
+
if (subscribers) {
|
|
670
|
+
this.transport.broadcast(message, Array.from(subscribers));
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
// Broadcast to all windows (fallback or non-keyed events)
|
|
675
|
+
this.transport.broadcast(message);
|
|
676
|
+
}
|
|
677
|
+
}exports.MessageBus=MessageBus;//# sourceMappingURL=MessageBus.js.map
|