@roomkit/worker 1.0.0

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.
Files changed (158) hide show
  1. package/README.md +122 -0
  2. package/dist/src/admin/admin.controller.d.ts +275 -0
  3. package/dist/src/admin/admin.controller.d.ts.map +1 -0
  4. package/dist/src/admin/admin.controller.js +296 -0
  5. package/dist/src/admin/admin.controller.js.map +1 -0
  6. package/dist/src/admin/admin.module.d.ts +3 -0
  7. package/dist/src/admin/admin.module.d.ts.map +1 -0
  8. package/dist/src/admin/admin.module.js +35 -0
  9. package/dist/src/admin/admin.module.js.map +1 -0
  10. package/dist/src/admin/admin.service.d.ts +282 -0
  11. package/dist/src/admin/admin.service.d.ts.map +1 -0
  12. package/dist/src/admin/admin.service.js +508 -0
  13. package/dist/src/admin/admin.service.js.map +1 -0
  14. package/dist/src/auth/auth.module.d.ts +10 -0
  15. package/dist/src/auth/auth.module.d.ts.map +1 -0
  16. package/dist/src/auth/auth.module.js +37 -0
  17. package/dist/src/auth/auth.module.js.map +1 -0
  18. package/dist/src/auth/auth.service.d.ts +21 -0
  19. package/dist/src/auth/auth.service.d.ts.map +1 -0
  20. package/dist/src/auth/auth.service.js +69 -0
  21. package/dist/src/auth/auth.service.js.map +1 -0
  22. package/dist/src/circuit-breaker/circuit-breaker.module.d.ts +3 -0
  23. package/dist/src/circuit-breaker/circuit-breaker.module.d.ts.map +1 -0
  24. package/dist/src/circuit-breaker/circuit-breaker.module.js +24 -0
  25. package/dist/src/circuit-breaker/circuit-breaker.module.js.map +1 -0
  26. package/dist/src/circuit-breaker/circuit-breaker.service.d.ts +89 -0
  27. package/dist/src/circuit-breaker/circuit-breaker.service.d.ts.map +1 -0
  28. package/dist/src/circuit-breaker/circuit-breaker.service.js +207 -0
  29. package/dist/src/circuit-breaker/circuit-breaker.service.js.map +1 -0
  30. package/dist/src/config/config.module.d.ts +3 -0
  31. package/dist/src/config/config.module.d.ts.map +1 -0
  32. package/dist/src/config/config.module.js +22 -0
  33. package/dist/src/config/config.module.js.map +1 -0
  34. package/dist/src/config/config.service.d.ts +19 -0
  35. package/dist/src/config/config.service.d.ts.map +1 -0
  36. package/dist/src/config/config.service.js +58 -0
  37. package/dist/src/config/config.service.js.map +1 -0
  38. package/dist/src/config/worker.config.d.ts +82 -0
  39. package/dist/src/config/worker.config.d.ts.map +1 -0
  40. package/dist/src/config/worker.config.js +35 -0
  41. package/dist/src/config/worker.config.js.map +1 -0
  42. package/dist/src/index.d.ts +48 -0
  43. package/dist/src/index.d.ts.map +1 -0
  44. package/dist/src/index.js +108 -0
  45. package/dist/src/index.js.map +1 -0
  46. package/dist/src/lifecycle/graceful-shutdown.service.d.ts +71 -0
  47. package/dist/src/lifecycle/graceful-shutdown.service.d.ts.map +1 -0
  48. package/dist/src/lifecycle/graceful-shutdown.service.js +221 -0
  49. package/dist/src/lifecycle/graceful-shutdown.service.js.map +1 -0
  50. package/dist/src/lifecycle/index.d.ts +2 -0
  51. package/dist/src/lifecycle/index.d.ts.map +1 -0
  52. package/dist/src/lifecycle/index.js +18 -0
  53. package/dist/src/lifecycle/index.js.map +1 -0
  54. package/dist/src/main.d.ts +2 -0
  55. package/dist/src/main.d.ts.map +1 -0
  56. package/dist/src/main.js +54 -0
  57. package/dist/src/main.js.map +1 -0
  58. package/dist/src/metrics/metrics.controller.d.ts +15 -0
  59. package/dist/src/metrics/metrics.controller.d.ts.map +1 -0
  60. package/dist/src/metrics/metrics.controller.js +44 -0
  61. package/dist/src/metrics/metrics.controller.js.map +1 -0
  62. package/dist/src/metrics/metrics.module.d.ts +7 -0
  63. package/dist/src/metrics/metrics.module.d.ts.map +1 -0
  64. package/dist/src/metrics/metrics.module.js +28 -0
  65. package/dist/src/metrics/metrics.module.js.map +1 -0
  66. package/dist/src/metrics/metrics.service.d.ts +65 -0
  67. package/dist/src/metrics/metrics.service.d.ts.map +1 -0
  68. package/dist/src/metrics/metrics.service.js +306 -0
  69. package/dist/src/metrics/metrics.service.js.map +1 -0
  70. package/dist/src/migration/migration.module.d.ts +3 -0
  71. package/dist/src/migration/migration.module.d.ts.map +1 -0
  72. package/dist/src/migration/migration.module.js +30 -0
  73. package/dist/src/migration/migration.module.js.map +1 -0
  74. package/dist/src/migration/migration.service.d.ts +68 -0
  75. package/dist/src/migration/migration.service.d.ts.map +1 -0
  76. package/dist/src/migration/migration.service.js +295 -0
  77. package/dist/src/migration/migration.service.js.map +1 -0
  78. package/dist/src/migration/room-migration.service.d.ts +92 -0
  79. package/dist/src/migration/room-migration.service.d.ts.map +1 -0
  80. package/dist/src/migration/room-migration.service.js +297 -0
  81. package/dist/src/migration/room-migration.service.js.map +1 -0
  82. package/dist/src/redis/redis.module.d.ts +3 -0
  83. package/dist/src/redis/redis.module.d.ts.map +1 -0
  84. package/dist/src/redis/redis.module.js +22 -0
  85. package/dist/src/redis/redis.module.js.map +1 -0
  86. package/dist/src/redis/redis.service.d.ts +68 -0
  87. package/dist/src/redis/redis.service.d.ts.map +1 -0
  88. package/dist/src/redis/redis.service.js +260 -0
  89. package/dist/src/redis/redis.service.js.map +1 -0
  90. package/dist/src/room/client-proxy.d.ts +43 -0
  91. package/dist/src/room/client-proxy.d.ts.map +1 -0
  92. package/dist/src/room/client-proxy.js +91 -0
  93. package/dist/src/room/client-proxy.js.map +1 -0
  94. package/dist/src/room/game-room.d.ts +243 -0
  95. package/dist/src/room/game-room.d.ts.map +1 -0
  96. package/dist/src/room/game-room.js +434 -0
  97. package/dist/src/room/game-room.js.map +1 -0
  98. package/dist/src/room/message-handler.service.d.ts +70 -0
  99. package/dist/src/room/message-handler.service.d.ts.map +1 -0
  100. package/dist/src/room/message-handler.service.js +541 -0
  101. package/dist/src/room/message-handler.service.js.map +1 -0
  102. package/dist/src/room/room-manager.service.d.ts +132 -0
  103. package/dist/src/room/room-manager.service.d.ts.map +1 -0
  104. package/dist/src/room/room-manager.service.js +571 -0
  105. package/dist/src/room/room-manager.service.js.map +1 -0
  106. package/dist/src/room/room-persistence.service.d.ts +101 -0
  107. package/dist/src/room/room-persistence.service.d.ts.map +1 -0
  108. package/dist/src/room/room-persistence.service.js +307 -0
  109. package/dist/src/room/room-persistence.service.js.map +1 -0
  110. package/dist/src/room/room-registry.service.d.ts +16 -0
  111. package/dist/src/room/room-registry.service.d.ts.map +1 -0
  112. package/dist/src/room/room-registry.service.js +60 -0
  113. package/dist/src/room/room-registry.service.js.map +1 -0
  114. package/dist/src/room/room.module.d.ts +15 -0
  115. package/dist/src/room/room.module.d.ts.map +1 -0
  116. package/dist/src/room/room.module.js +55 -0
  117. package/dist/src/room/room.module.js.map +1 -0
  118. package/dist/src/room/rooms/echo-room.d.ts +18 -0
  119. package/dist/src/room/rooms/echo-room.d.ts.map +1 -0
  120. package/dist/src/room/rooms/echo-room.js +85 -0
  121. package/dist/src/room/rooms/echo-room.js.map +1 -0
  122. package/dist/src/room/rooms/index.d.ts +2 -0
  123. package/dist/src/room/rooms/index.d.ts.map +1 -0
  124. package/dist/src/room/rooms/index.js +6 -0
  125. package/dist/src/room/rooms/index.js.map +1 -0
  126. package/dist/src/worker.module.d.ts +10 -0
  127. package/dist/src/worker.module.d.ts.map +1 -0
  128. package/dist/src/worker.module.js +46 -0
  129. package/dist/src/worker.module.js.map +1 -0
  130. package/dist/test/circuit-breaker/circuit-breaker.service.spec.d.ts +2 -0
  131. package/dist/test/circuit-breaker/circuit-breaker.service.spec.d.ts.map +1 -0
  132. package/dist/test/circuit-breaker/circuit-breaker.service.spec.js +220 -0
  133. package/dist/test/circuit-breaker/circuit-breaker.service.spec.js.map +1 -0
  134. package/dist/test/integration/admin-api.spec.d.ts +2 -0
  135. package/dist/test/integration/admin-api.spec.d.ts.map +1 -0
  136. package/dist/test/integration/admin-api.spec.js +246 -0
  137. package/dist/test/integration/admin-api.spec.js.map +1 -0
  138. package/dist/test/migration/game-room-migration.spec.d.ts +2 -0
  139. package/dist/test/migration/game-room-migration.spec.d.ts.map +1 -0
  140. package/dist/test/migration/game-room-migration.spec.js +222 -0
  141. package/dist/test/migration/game-room-migration.spec.js.map +1 -0
  142. package/dist/test/room/client-proxy.spec.d.ts +2 -0
  143. package/dist/test/room/client-proxy.spec.d.ts.map +1 -0
  144. package/dist/test/room/client-proxy.spec.js +117 -0
  145. package/dist/test/room/client-proxy.spec.js.map +1 -0
  146. package/dist/test/room/game-room.spec.d.ts +2 -0
  147. package/dist/test/room/game-room.spec.d.ts.map +1 -0
  148. package/dist/test/room/game-room.spec.js +219 -0
  149. package/dist/test/room/game-room.spec.js.map +1 -0
  150. package/dist/test/room/room-manager.service.spec.d.ts +2 -0
  151. package/dist/test/room/room-manager.service.spec.d.ts.map +1 -0
  152. package/dist/test/room/room-manager.service.spec.js +280 -0
  153. package/dist/test/room/room-manager.service.spec.js.map +1 -0
  154. package/dist/test/setup.d.ts +2 -0
  155. package/dist/test/setup.d.ts.map +1 -0
  156. package/dist/test/setup.js +56 -0
  157. package/dist/test/setup.js.map +1 -0
  158. package/package.json +74 -0
@@ -0,0 +1,571 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var RoomManagerService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.RoomManagerService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const core_1 = require("@roomkit/core");
16
+ const config_service_1 = require("../config/config.service");
17
+ const redis_service_1 = require("../redis/redis.service");
18
+ const game_room_1 = require("./game-room");
19
+ const client_proxy_1 = require("./client-proxy");
20
+ const room_persistence_service_1 = require("./room-persistence.service");
21
+ /**
22
+ * 房间管理器
23
+ */
24
+ let RoomManagerService = RoomManagerService_1 = class RoomManagerService {
25
+ configService;
26
+ redisService;
27
+ persistenceService;
28
+ logger = new common_1.Logger(RoomManagerService_1.name);
29
+ rooms = new Map();
30
+ roomTypes = new Map();
31
+ constructor(configService, redisService, persistenceService) {
32
+ this.configService = configService;
33
+ this.redisService = redisService;
34
+ this.persistenceService = persistenceService;
35
+ }
36
+ migrationService;
37
+ /**
38
+ * 设置 MigrationService(从 MigrationModule 调用)
39
+ */
40
+ setMigrationService(migrationService) {
41
+ this.migrationService = migrationService;
42
+ }
43
+ /**
44
+ * 模块初始化,清理孤儿房间数据
45
+ */
46
+ async onModuleInit() {
47
+ this.logger.log('Initializing room manager and cleaning orphan rooms...');
48
+ await this.cleanOrphanRooms();
49
+ // 启动定期清理任务(每5分钟执行一次)
50
+ setInterval(async () => {
51
+ try {
52
+ await this.cleanOrphanRooms();
53
+ }
54
+ catch (error) {
55
+ this.logger.error('Failed to clean orphan rooms:', error);
56
+ }
57
+ }, 5 * 60 * 1000); // 5分钟
58
+ }
59
+ /**
60
+ * 注册房间类型
61
+ */
62
+ registerRoomType(gameType, roomClass) {
63
+ this.roomTypes.set(gameType, roomClass);
64
+ this.logger.log(`Room type registered: ${gameType}`);
65
+ }
66
+ /**
67
+ * 获取所有已注册的房间类型
68
+ */
69
+ getRegisteredGameTypes() {
70
+ return Array.from(this.roomTypes.keys());
71
+ }
72
+ /**
73
+ * 创建房间
74
+ */
75
+ async createRoom(roomId, gameType, maxPlayers, config, creatorClient) {
76
+ // 检查房间数量限制
77
+ if (this.rooms.size >= this.configService.maxRooms) {
78
+ this.logger.warn('Max rooms reached');
79
+ return null;
80
+ }
81
+ // 获取房间类型
82
+ const RoomClass = this.roomTypes.get(gameType);
83
+ if (!RoomClass) {
84
+ this.logger.warn(`Unknown game type: ${gameType}`);
85
+ return null;
86
+ }
87
+ // 创建房间实例
88
+ const room = new RoomClass(roomId, gameType, maxPlayers, config);
89
+ try {
90
+ // 调用onCreate
91
+ await room.onCreate(config);
92
+ room.status = 'waiting';
93
+ // 存储房间
94
+ this.rooms.set(roomId, room);
95
+ // 设置持久化回调
96
+ room.persistenceCallback = (event) => {
97
+ this.persistenceService.recordEvent(roomId, event);
98
+ };
99
+ // 启动持久化
100
+ await this.persistenceService.startPersistence(roomId, () => room.getState());
101
+ // 更新Redis
102
+ await this.updateRoomInRedis(room);
103
+ // 更新统计
104
+ await this.updateStats();
105
+ this.logger.log(`Room created: ${roomId}, type: ${gameType}`);
106
+ return room;
107
+ }
108
+ catch (error) {
109
+ this.logger.error(`Failed to create room: ${error}`);
110
+ return null;
111
+ }
112
+ }
113
+ /**
114
+ * 获取房间
115
+ */
116
+ getRoom(roomId) {
117
+ return this.rooms.get(roomId);
118
+ }
119
+ /**
120
+ * 玩家加入房间
121
+ *
122
+ * 认证流程(Colyseus 风格):
123
+ * 1. 如果房间类定义了 static onAuth,先调用静态认证
124
+ * 2. 调用实例的 onAuth 方法
125
+ * 3. 两者都通过后才允许加入
126
+ *
127
+ * @param room 目标房间
128
+ * @param client 客户端代理
129
+ * @param options 加入选项
130
+ * @param context 认证上下文(可选)
131
+ */
132
+ async joinRoom(room, client, options = {}, context) {
133
+ // 确保有 userId(必须在 Gateway 层 gw:auth 中设置)
134
+ if (!client.userId) {
135
+ this.logger.warn(`Cannot join room: userId not set. User must authenticate via gw:auth first.`);
136
+ return false;
137
+ }
138
+ // 检查房间状态
139
+ if (room.status === 'disposed') {
140
+ return false;
141
+ }
142
+ // 检查人数
143
+ if (room.playerCount >= room.maxPlayers) {
144
+ return false;
145
+ }
146
+ // 构建认证上下文
147
+ const authContext = context || {
148
+ connectionId: client.connectionId,
149
+ gatewayId: client.gatewayId,
150
+ timestamp: Date.now(),
151
+ };
152
+ // 1. 静态认证(如果定义了)- 只验证权限,不设置 userId
153
+ const RoomClass = room.constructor;
154
+ let staticAuthData = undefined;
155
+ if (RoomClass.onAuth !== game_room_1.GameRoom.onAuth) {
156
+ try {
157
+ const token = options.token || '';
158
+ staticAuthData = await RoomClass.onAuth(token, options, authContext);
159
+ if (!staticAuthData) {
160
+ this.logger.debug(`Static onAuth rejected: ${client.userId}`);
161
+ return false;
162
+ }
163
+ // 将认证数据附加到 client.auth(排除 userId)
164
+ if (typeof staticAuthData === 'object' && staticAuthData !== null) {
165
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
166
+ const { userId: _, ...authData } = staticAuthData;
167
+ client.auth = authData;
168
+ }
169
+ else {
170
+ client.auth = staticAuthData;
171
+ }
172
+ }
173
+ catch (error) {
174
+ if (error instanceof core_1.ServerError) {
175
+ await client.send(core_1.MessageType.ERROR, {
176
+ code: error.code,
177
+ message: error.message,
178
+ });
179
+ }
180
+ this.logger.debug(`Static onAuth error: ${error}`);
181
+ return false;
182
+ }
183
+ }
184
+ // 2. 实例认证 - 只验证权限,不设置 userId
185
+ try {
186
+ const instanceAuthResult = await room.onAuth(client, options, authContext);
187
+ if (!instanceAuthResult) {
188
+ this.logger.debug(`Instance onAuth rejected: ${client.userId}`);
189
+ return false;
190
+ }
191
+ // 合并认证数据到 client.auth(排除 userId)
192
+ if (typeof instanceAuthResult === 'object' && instanceAuthResult !== null) {
193
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
194
+ const { userId: _, ...authData } = instanceAuthResult;
195
+ const existingAuth = (typeof client.auth === 'object' && client.auth !== null)
196
+ ? client.auth
197
+ : {};
198
+ client.auth = { ...existingAuth, ...authData };
199
+ }
200
+ }
201
+ catch (error) {
202
+ if (error instanceof core_1.ServerError) {
203
+ await client.send(core_1.MessageType.ERROR, {
204
+ code: error.code,
205
+ message: error.message,
206
+ });
207
+ }
208
+ this.logger.debug(`Instance onAuth error: ${error}`);
209
+ return false;
210
+ }
211
+ // 添加玩家
212
+ const playerInfo = {
213
+ userId: client.userId,
214
+ joinedAt: Date.now(),
215
+ };
216
+ room.addPlayer(client, playerInfo);
217
+ // 更新Redis房间成员
218
+ await this.redisService.client.hset(core_1.RedisKeys.roomMembers(room.roomId), client.userId, JSON.stringify({
219
+ gatewayId: client.gatewayId,
220
+ connectionId: client.connectionId,
221
+ joinedAt: Date.now(),
222
+ }));
223
+ // 通知Gateway更新用户房间状态
224
+ await this.notifyUserJoinedRoom(client, room.roomId);
225
+ // 调用onJoin,传入认证数据
226
+ await room.onJoin(client, options, staticAuthData);
227
+ // 更新房间状态
228
+ if (room.status === 'waiting' && room.playerCount >= 2) {
229
+ room.status = 'active';
230
+ }
231
+ // 更新 Redis 中的房间信息(玩家数、状态等)
232
+ await this.updateRoomInRedis(room);
233
+ // 更新统计
234
+ await this.updateStats();
235
+ this.logger.log(`Player ${client.userId} joined room ${room.roomId}`);
236
+ return true;
237
+ }
238
+ /**
239
+ * 玩家离开房间
240
+ */
241
+ async leaveRoom(room, userId, reason) {
242
+ const client = room.getPlayer(userId);
243
+ if (!client)
244
+ return;
245
+ // 调用onLeave
246
+ await room.onLeave(client, reason);
247
+ // 移除玩家
248
+ room.removePlayer(userId);
249
+ // 更新Redis
250
+ await this.redisService.client.hdel(core_1.RedisKeys.roomMembers(room.roomId), userId);
251
+ await this.redisService.client.del(core_1.RedisKeys.userRoom(userId));
252
+ // 通知Gateway
253
+ await this.notifyUserLeftRoom(client, room.roomId, reason);
254
+ // 检查是否需要销毁房间
255
+ if (room.playerCount === 0 && room.autoDispose) {
256
+ await this.disposeRoom(room.roomId);
257
+ }
258
+ else {
259
+ // 更新房间状态
260
+ if (room.status === 'active' && room.playerCount < 2) {
261
+ room.status = 'paused';
262
+ }
263
+ // 更新 Redis 中的房间信息
264
+ await this.updateRoomInRedis(room);
265
+ }
266
+ // 更新统计
267
+ await this.updateStats();
268
+ this.logger.log(`Player ${userId} left room ${room.roomId}, reason: ${reason}`);
269
+ }
270
+ /**
271
+ * 销毁房间
272
+ */
273
+ async disposeRoom(roomId) {
274
+ const room = this.rooms.get(roomId);
275
+ if (!room)
276
+ return;
277
+ // 通知所有玩家房间关闭
278
+ for (const [userId, client] of room.players) {
279
+ await client.send(core_1.MessageType.ROOM_CLOSING, { reason: 'disposed' });
280
+ await this.notifyUserLeftRoom(client, roomId, 'room-disposed');
281
+ }
282
+ // 调用onDispose
283
+ await room.dispose();
284
+ // 停止持久化
285
+ await this.persistenceService.stopPersistence(roomId);
286
+ // 从内存移除
287
+ this.rooms.delete(roomId);
288
+ // 清理Redis(包括持久化数据)
289
+ await this.cleanupRoomInRedis(roomId, room.gameType);
290
+ await this.persistenceService.cleanupRoomData(roomId);
291
+ // 更新统计
292
+ await this.updateStats();
293
+ this.logger.log(`Room disposed: ${roomId}`);
294
+ }
295
+ /**
296
+ * 处理客户端断开
297
+ */
298
+ async handleDisconnect(roomId, userId) {
299
+ const room = this.rooms.get(roomId);
300
+ if (room) {
301
+ await this.leaveRoom(room, userId, 'disconnected');
302
+ }
303
+ }
304
+ /**
305
+ * 更新Redis中的房间信息
306
+ */
307
+ async updateRoomInRedis(room) {
308
+ const roomInfo = {
309
+ roomId: room.roomId,
310
+ gameType: room.gameType,
311
+ playerCount: room.playerCount,
312
+ maxPlayers: room.maxPlayers,
313
+ status: room.status,
314
+ workerId: this.configService.workerId,
315
+ createdAt: room.createdAt,
316
+ };
317
+ await this.redisService.client.set(core_1.RedisKeys.roomState(room.roomId), JSON.stringify(roomInfo));
318
+ await this.redisService.client.sadd(core_1.RedisKeys.roomsAll(), room.roomId);
319
+ await this.redisService.client.sadd(core_1.RedisKeys.roomsByType(room.gameType), room.roomId);
320
+ }
321
+ /**
322
+ * 清理Redis中的房间数据
323
+ */
324
+ async cleanupRoomInRedis(roomId, gameType) {
325
+ await this.redisService.client.del(core_1.RedisKeys.roomWorker(roomId));
326
+ await this.redisService.client.del(core_1.RedisKeys.roomMembers(roomId));
327
+ await this.redisService.client.del(core_1.RedisKeys.roomState(roomId));
328
+ await this.redisService.client.srem(core_1.RedisKeys.roomsAll(), roomId);
329
+ await this.redisService.client.srem(core_1.RedisKeys.roomsByType(gameType), roomId);
330
+ }
331
+ /**
332
+ * 通知Gateway用户加入房间
333
+ */
334
+ async notifyUserJoinedRoom(client, roomId) {
335
+ // 获取房间信息(包含 gameType)
336
+ const room = this.rooms.get(roomId);
337
+ const gameType = room?.gameType || 'unknown';
338
+ const message = {
339
+ type: 'user-joined-room',
340
+ workerId: this.configService.workerId,
341
+ connectionId: client.connectionId,
342
+ userId: client.userId,
343
+ roomId,
344
+ payload: {
345
+ gameType, // 传递房间类型给 Gateway
346
+ },
347
+ timestamp: Date.now(),
348
+ };
349
+ await this.redisService.publish(core_1.RedisChannels.rpcGateway(client.gatewayId), message);
350
+ }
351
+ /**
352
+ * 通知Gateway用户离开房间
353
+ */
354
+ async notifyUserLeftRoom(client, roomId, reason) {
355
+ const message = {
356
+ type: 'user-left-room',
357
+ workerId: this.configService.workerId,
358
+ connectionId: client.connectionId,
359
+ userId: client.userId,
360
+ roomId,
361
+ reason,
362
+ timestamp: Date.now(),
363
+ };
364
+ await this.redisService.publish(core_1.RedisChannels.rpcGateway(client.gatewayId), message);
365
+ }
366
+ /**
367
+ * 更新Worker统计信息
368
+ */
369
+ async updateStats() {
370
+ let playerCount = 0;
371
+ for (const room of this.rooms.values()) {
372
+ playerCount += room.playerCount;
373
+ }
374
+ await this.redisService.updateStats(this.rooms.size, playerCount);
375
+ }
376
+ /**
377
+ * 获取所有房间
378
+ */
379
+ getAllRooms() {
380
+ return this.rooms;
381
+ }
382
+ /**
383
+ * 获取房间数量
384
+ */
385
+ getRoomCount() {
386
+ return this.rooms.size;
387
+ }
388
+ // ============ 迁移相关方法 ============
389
+ /**
390
+ * 从快照创建房间(用于迁移恢复)
391
+ */
392
+ async createRoomFromSnapshot(snapshot) {
393
+ // 获取房间类型
394
+ const RoomClass = this.roomTypes.get(snapshot.gameType);
395
+ if (!RoomClass) {
396
+ this.logger.warn(`Unknown game type for migration: ${snapshot.gameType}`);
397
+ return null;
398
+ }
399
+ // 创建房间实例
400
+ const room = new RoomClass(snapshot.roomId, snapshot.gameType, snapshot.maxPlayers, snapshot.config);
401
+ // 设置创建时间为原始时间
402
+ room.createdAt = snapshot.createdAt;
403
+ // 存储房间
404
+ this.rooms.set(snapshot.roomId, room);
405
+ // 更新Redis(使用当前Worker ID)
406
+ await this.updateRoomInRedis(room);
407
+ this.logger.log(`Room created from snapshot: ${snapshot.roomId}`);
408
+ return room;
409
+ }
410
+ /**
411
+ * 重建客户端代理(用于迁移恢复)
412
+ */
413
+ async rebuildClientProxy(room, userId, gatewayId, connectionId, playerInfo) {
414
+ // 创建新的 ClientProxy
415
+ const client = new client_proxy_1.ClientProxy(userId, gatewayId, connectionId, this.redisService, this.configService.workerId);
416
+ client.roomId = room.roomId;
417
+ // 添加到房间
418
+ room.players.set(userId, client);
419
+ room.playerInfos.set(userId, playerInfo);
420
+ // 更新 Redis 房间成员
421
+ await this.redisService.client.hset(core_1.RedisKeys.roomMembers(room.roomId), userId, JSON.stringify({
422
+ gatewayId,
423
+ connectionId,
424
+ joinedAt: playerInfo.joinedAt,
425
+ }));
426
+ // 更新 Redis 用户房间映射
427
+ await this.redisService.client.set(core_1.RedisKeys.userRoom(userId), room.roomId);
428
+ this.logger.debug(`Rebuilt client proxy for user ${userId} in room ${room.roomId}`);
429
+ }
430
+ /**
431
+ * 移除房间(不通知玩家,用于迁移清理)
432
+ */
433
+ removeRoomSilently(roomId) {
434
+ this.rooms.delete(roomId);
435
+ }
436
+ /**
437
+ * 清理孤儿房间数据
438
+ * 检查Redis中的房间数据,如果对应的Worker不是当前Worker或房间实例不存在,则清理
439
+ */
440
+ async cleanOrphanRooms() {
441
+ try {
442
+ // 获取所有房间键
443
+ const roomKeys = await this.redisService.client.keys('gw:room:*:worker');
444
+ const orphanRooms = [];
445
+ for (const roomWorkerKey of roomKeys) {
446
+ const roomId = roomWorkerKey.split(':')[2]; // 从 "gw:room:xxx:worker" 提取房间ID
447
+ const assignedWorkerId = await this.redisService.client.get(roomWorkerKey);
448
+ // 检查是否是当前Worker负责的房间
449
+ if (assignedWorkerId === this.configService.workerId) {
450
+ // 检查本地是否有房间实例
451
+ if (!this.rooms.has(roomId)) {
452
+ orphanRooms.push(roomId);
453
+ }
454
+ }
455
+ }
456
+ // 清理孤儿房间
457
+ if (orphanRooms.length > 0) {
458
+ this.logger.warn(`Found ${orphanRooms.length} orphan rooms, cleaning up: ${orphanRooms.join(', ')}`);
459
+ for (const roomId of orphanRooms) {
460
+ await this.cleanRoomData(roomId);
461
+ }
462
+ this.logger.log(`Cleaned up ${orphanRooms.length} orphan rooms`);
463
+ }
464
+ }
465
+ catch (error) {
466
+ this.logger.error('Error during orphan room cleanup:', error);
467
+ }
468
+ }
469
+ /**
470
+ * 清理指定房间的所有Redis数据
471
+ */
472
+ async cleanRoomData(roomId) {
473
+ try {
474
+ const keys = [
475
+ core_1.RedisKeys.roomWorker(roomId),
476
+ core_1.RedisKeys.roomMembers(roomId),
477
+ core_1.RedisKeys.roomState(roomId),
478
+ ];
479
+ // 获取房间成员,清理用户房间映射
480
+ try {
481
+ const members = await this.redisService.client.hgetall(core_1.RedisKeys.roomMembers(roomId));
482
+ for (const userId of Object.keys(members)) {
483
+ await this.redisService.client.del(core_1.RedisKeys.userRoom(userId));
484
+ }
485
+ }
486
+ catch (error) {
487
+ // 忽略成员清理错误
488
+ }
489
+ // 删除房间相关键
490
+ await this.redisService.client.del(...keys);
491
+ this.logger.log(`Cleaned room data for ${roomId}`);
492
+ }
493
+ catch (error) {
494
+ this.logger.error(`Failed to clean room data for ${roomId}:`, error);
495
+ }
496
+ }
497
+ /**
498
+ */
499
+ removeRoom(roomId) {
500
+ this.rooms.delete(roomId);
501
+ }
502
+ /**
503
+ * 获取总玩家数
504
+ */
505
+ getTotalPlayerCount() {
506
+ let total = 0;
507
+ for (const room of this.rooms.values()) {
508
+ total += room.playerCount;
509
+ }
510
+ return total;
511
+ }
512
+ /**
513
+ * 从快照恢复房间(用于迁移)
514
+ */
515
+ async restoreRoom(snapshot) {
516
+ const { roomId, state } = snapshot;
517
+ // 检查房间是否已存在
518
+ if (this.rooms.has(roomId)) {
519
+ this.logger.warn(`Room ${roomId} already exists, cannot restore`);
520
+ return null;
521
+ }
522
+ // 检查房间数量限制
523
+ if (this.rooms.size >= this.configService.maxRooms) {
524
+ this.logger.warn('Max rooms reached, cannot restore');
525
+ return null;
526
+ }
527
+ // 获取房间类型
528
+ const gameType = state.gameType || snapshot.gameType;
529
+ const RoomClass = this.roomTypes.get(gameType);
530
+ if (!RoomClass) {
531
+ this.logger.warn(`Unknown game type: ${gameType}, cannot restore`);
532
+ return null;
533
+ }
534
+ try {
535
+ // 创建房间实例
536
+ const room = new RoomClass(roomId, gameType, state.maxPlayers || 4, snapshot.config || {});
537
+ // 标记为迁移恢复
538
+ room.sourceWorkerId = snapshot.workerId;
539
+ // 恢复房间状态
540
+ room.restoreFromSnapshot(snapshot);
541
+ // 调用迁移完成钩子
542
+ await room.onMigrationComplete();
543
+ // 存储房间
544
+ this.rooms.set(roomId, room);
545
+ // 设置持久化回调
546
+ room.persistenceCallback = (event) => {
547
+ this.persistenceService.recordEvent(roomId, event);
548
+ };
549
+ // 启动持久化
550
+ await this.persistenceService.startPersistence(roomId, () => room.getState());
551
+ // 更新Redis
552
+ await this.updateRoomInRedis(room);
553
+ // 更新统计
554
+ await this.updateStats();
555
+ this.logger.log(`Room restored: ${roomId}, type: ${gameType}, from worker: ${snapshot.workerId}`);
556
+ return room;
557
+ }
558
+ catch (error) {
559
+ this.logger.error(`Failed to restore room ${roomId}:`, error);
560
+ return null;
561
+ }
562
+ }
563
+ };
564
+ exports.RoomManagerService = RoomManagerService;
565
+ exports.RoomManagerService = RoomManagerService = RoomManagerService_1 = __decorate([
566
+ (0, common_1.Injectable)(),
567
+ __metadata("design:paramtypes", [config_service_1.ConfigService,
568
+ redis_service_1.RedisService,
569
+ room_persistence_service_1.RoomPersistenceService])
570
+ ], RoomManagerService);
571
+ //# sourceMappingURL=room-manager.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-manager.service.js","sourceRoot":"","sources":["../../../src/room/room-manager.service.ts"],"names":[],"mappings":"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"}