@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,101 @@
1
+ /**
2
+ * 房间持久化服务
3
+ *
4
+ * 功能:
5
+ * 1. 定期保存房间快照到Redis
6
+ * 2. 记录增量状态变更事件
7
+ * 3. 从Redis恢复房间状态
8
+ * 4. 管理持久化任务生命周期
9
+ *
10
+ * 设计:
11
+ * - 快照:每10秒保存完整状态
12
+ * - 事件:每1秒批量写入增量事件
13
+ * - 恢复:快照 + 增量事件 = 完整状态
14
+ */
15
+ import { RedisService } from '../redis/redis.service.js';
16
+ import { ConfigService } from '../config/config.service.js';
17
+ export interface StateChangeEvent {
18
+ type: string;
19
+ version: number;
20
+ data: any;
21
+ timestamp: number;
22
+ }
23
+ export interface RoomSnapshot {
24
+ roomId: string;
25
+ state: any;
26
+ version: number;
27
+ timestamp: number;
28
+ workerId: string;
29
+ }
30
+ export interface PersistenceOptions {
31
+ /** 快照间隔(毫秒) */
32
+ snapshotInterval?: number;
33
+ /** 事件批量写入间隔(毫秒) */
34
+ eventFlushInterval?: number;
35
+ /** 快照TTL(秒) */
36
+ snapshotTTL?: number;
37
+ /** 事件TTL(秒) */
38
+ eventTTL?: number;
39
+ /** 是否启用持久化 */
40
+ enabled?: boolean;
41
+ }
42
+ export declare class RoomPersistenceService {
43
+ private readonly redis;
44
+ private readonly config;
45
+ private readonly logger;
46
+ private readonly DEFAULT_OPTIONS;
47
+ private options;
48
+ private eventBuffer;
49
+ private persistenceTasks;
50
+ private roomStateGetters;
51
+ constructor(redis: RedisService, config: ConfigService);
52
+ /**
53
+ * 配置持久化选项
54
+ */
55
+ configure(options: PersistenceOptions): void;
56
+ /**
57
+ * 启动房间持久化
58
+ */
59
+ startPersistence(roomId: string, stateGetter: () => any): Promise<void>;
60
+ /**
61
+ * 停止房间持久化
62
+ */
63
+ stopPersistence(roomId: string): Promise<void>;
64
+ /**
65
+ * 记录状态变更事件
66
+ */
67
+ recordEvent(roomId: string, event: StateChangeEvent): void;
68
+ /**
69
+ * 保存房间快照
70
+ */
71
+ saveSnapshot(roomId: string): Promise<void>;
72
+ /**
73
+ * 批量写入事件
74
+ */
75
+ flushEvents(roomId: string): Promise<void>;
76
+ /**
77
+ * 恢复房间状态
78
+ */
79
+ recoverRoom(roomId: string): Promise<RoomSnapshot | null>;
80
+ /**
81
+ * 应用事件到状态
82
+ */
83
+ private applyEvent;
84
+ /**
85
+ * 清理房间持久化数据
86
+ */
87
+ cleanupRoomData(roomId: string): Promise<void>;
88
+ /**
89
+ * 获取持久化统计信息
90
+ */
91
+ getStats(): {
92
+ activeRooms: number;
93
+ bufferedEvents: number;
94
+ options: Required<PersistenceOptions>;
95
+ };
96
+ /**
97
+ * 模块销毁时清理
98
+ */
99
+ onModuleDestroy(): Promise<void>;
100
+ }
101
+ //# sourceMappingURL=room-persistence.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-persistence.service.d.ts","sourceRoot":"","sources":["../../../src/room/room-persistence.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,GAAG,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAOD,qBACa,sBAAsB;IAwB/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAxBzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAGlE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAM9B;IAEF,OAAO,CAAC,OAAO,CAA+B;IAG9C,OAAO,CAAC,WAAW,CAAyC;IAG5D,OAAO,CAAC,gBAAgB,CAAsC;IAG9D,OAAO,CAAC,gBAAgB,CAAgC;gBAGrC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,aAAa;IAaxC;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAK5C;;OAEG;IACG,gBAAgB,CACpB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,GACrB,OAAO,CAAC,IAAI,CAAC;IAkDhB;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCpD;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAqB1D;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkChD;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA+D/D;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD;;OAEG;IACH,QAAQ,IAAI;QACV,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;KACvC;IAaD;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAWvC"}
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ /**
3
+ * 房间持久化服务
4
+ *
5
+ * 功能:
6
+ * 1. 定期保存房间快照到Redis
7
+ * 2. 记录增量状态变更事件
8
+ * 3. 从Redis恢复房间状态
9
+ * 4. 管理持久化任务生命周期
10
+ *
11
+ * 设计:
12
+ * - 快照:每10秒保存完整状态
13
+ * - 事件:每1秒批量写入增量事件
14
+ * - 恢复:快照 + 增量事件 = 完整状态
15
+ */
16
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
17
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
+ 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;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ };
22
+ var __metadata = (this && this.__metadata) || function (k, v) {
23
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
24
+ };
25
+ var RoomPersistenceService_1;
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.RoomPersistenceService = void 0;
28
+ const common_1 = require("@nestjs/common");
29
+ const redis_service_js_1 = require("../redis/redis.service.js");
30
+ const config_service_js_1 = require("../config/config.service.js");
31
+ let RoomPersistenceService = RoomPersistenceService_1 = class RoomPersistenceService {
32
+ redis;
33
+ config;
34
+ logger = new common_1.Logger(RoomPersistenceService_1.name);
35
+ // 默认配置
36
+ DEFAULT_OPTIONS = {
37
+ snapshotInterval: 10000, // 10秒
38
+ eventFlushInterval: 1000, // 1秒
39
+ snapshotTTL: 3600, // 1小时
40
+ eventTTL: 3600, // 1小时
41
+ enabled: true,
42
+ };
43
+ options;
44
+ // 事件缓冲区
45
+ eventBuffer = new Map();
46
+ // 持久化任务
47
+ persistenceTasks = new Map();
48
+ // 房间状态获取函数(由外部注入)
49
+ roomStateGetters = new Map();
50
+ constructor(redis, config) {
51
+ this.redis = redis;
52
+ this.config = config;
53
+ // 从配置服务读取持久化选项
54
+ this.options = {
55
+ ...this.DEFAULT_OPTIONS,
56
+ enabled: this.config.persistenceEnabled,
57
+ snapshotInterval: this.config.snapshotInterval,
58
+ eventFlushInterval: this.config.eventFlushInterval,
59
+ snapshotTTL: this.config.snapshotTTL,
60
+ eventTTL: this.config.eventTTL,
61
+ };
62
+ }
63
+ /**
64
+ * 配置持久化选项
65
+ */
66
+ configure(options) {
67
+ this.options = { ...this.options, ...options };
68
+ this.logger.log(`Persistence configured: ${JSON.stringify(this.options)}`);
69
+ }
70
+ /**
71
+ * 启动房间持久化
72
+ */
73
+ async startPersistence(roomId, stateGetter) {
74
+ if (!this.options.enabled) {
75
+ this.logger.debug(`Persistence disabled, skipping room ${roomId}`);
76
+ return;
77
+ }
78
+ if (this.persistenceTasks.has(roomId)) {
79
+ this.logger.warn(`Persistence already started for room ${roomId}`);
80
+ return;
81
+ }
82
+ this.logger.log(`Starting persistence for room ${roomId}`);
83
+ // 保存状态获取函数
84
+ this.roomStateGetters.set(roomId, stateGetter);
85
+ // 初始化事件缓冲区
86
+ this.eventBuffer.set(roomId, []);
87
+ // 1. 定期快照
88
+ const snapshotTimer = setInterval(async () => {
89
+ try {
90
+ await this.saveSnapshot(roomId);
91
+ }
92
+ catch (error) {
93
+ const err = error;
94
+ this.logger.error(`Failed to save snapshot for room ${roomId}: ${err.message}`);
95
+ }
96
+ }, this.options.snapshotInterval);
97
+ // 2. 定期批量写入事件
98
+ const eventTimer = setInterval(async () => {
99
+ try {
100
+ await this.flushEvents(roomId);
101
+ }
102
+ catch (error) {
103
+ const err = error;
104
+ this.logger.error(`Failed to flush events for room ${roomId}: ${err.message}`);
105
+ }
106
+ }, this.options.eventFlushInterval);
107
+ // 保存定时器引用
108
+ this.persistenceTasks.set(roomId, { snapshotTimer, eventTimer });
109
+ // 立即保存一次初始快照
110
+ await this.saveSnapshot(roomId);
111
+ }
112
+ /**
113
+ * 停止房间持久化
114
+ */
115
+ async stopPersistence(roomId) {
116
+ const tasks = this.persistenceTasks.get(roomId);
117
+ if (!tasks) {
118
+ this.logger.debug(`No persistence task found for room ${roomId}`);
119
+ return;
120
+ }
121
+ this.logger.log(`Stopping persistence for room ${roomId}`);
122
+ // 停止定时器
123
+ clearInterval(tasks.snapshotTimer);
124
+ clearInterval(tasks.eventTimer);
125
+ // 最后一次保存
126
+ try {
127
+ await this.flushEvents(roomId);
128
+ await this.saveSnapshot(roomId);
129
+ }
130
+ catch (error) {
131
+ const err = error;
132
+ this.logger.error(`Failed to save final state for room ${roomId}: ${err.message}`);
133
+ }
134
+ // 清理
135
+ this.persistenceTasks.delete(roomId);
136
+ this.roomStateGetters.delete(roomId);
137
+ this.eventBuffer.delete(roomId);
138
+ this.logger.log(`Persistence stopped for room ${roomId}`);
139
+ }
140
+ /**
141
+ * 记录状态变更事件
142
+ */
143
+ recordEvent(roomId, event) {
144
+ if (!this.options.enabled) {
145
+ return;
146
+ }
147
+ const buffer = this.eventBuffer.get(roomId);
148
+ if (!buffer) {
149
+ this.logger.warn(`No event buffer for room ${roomId}, event dropped`);
150
+ return;
151
+ }
152
+ buffer.push({
153
+ ...event,
154
+ timestamp: event.timestamp || Date.now(),
155
+ });
156
+ this.logger.debug(`Event recorded for room ${roomId}: ${event.type} v${event.version}`);
157
+ }
158
+ /**
159
+ * 保存房间快照
160
+ */
161
+ async saveSnapshot(roomId) {
162
+ const stateGetter = this.roomStateGetters.get(roomId);
163
+ if (!stateGetter) {
164
+ this.logger.warn(`No state getter for room ${roomId}, skipping snapshot`);
165
+ return;
166
+ }
167
+ try {
168
+ const state = stateGetter();
169
+ const snapshot = {
170
+ roomId,
171
+ state: JSON.stringify(state),
172
+ version: state.version?.toString() || '0',
173
+ timestamp: Date.now().toString(),
174
+ workerId: this.config.workerId,
175
+ };
176
+ await this.redis.client.hset(`gw:room:${roomId}:snapshot`, snapshot);
177
+ await this.redis.client.expire(`gw:room:${roomId}:snapshot`, this.options.snapshotTTL);
178
+ this.logger.debug(`Saved snapshot for room ${roomId}, version ${snapshot.version}`);
179
+ }
180
+ catch (error) {
181
+ const err = error;
182
+ throw new Error(`Failed to save snapshot: ${err.message}`);
183
+ }
184
+ }
185
+ /**
186
+ * 批量写入事件
187
+ */
188
+ async flushEvents(roomId) {
189
+ const buffer = this.eventBuffer.get(roomId);
190
+ if (!buffer || buffer.length === 0) {
191
+ return;
192
+ }
193
+ try {
194
+ // 序列化事件
195
+ const serialized = buffer.map((event) => JSON.stringify(event));
196
+ // 批量写入Redis List
197
+ await this.redis.client.rpush(`gw:room:${roomId}:events`, ...serialized);
198
+ // 设置TTL
199
+ await this.redis.client.expire(`gw:room:${roomId}:events`, this.options.eventTTL);
200
+ this.logger.debug(`Flushed ${buffer.length} events for room ${roomId}`);
201
+ // 清空缓冲区
202
+ this.eventBuffer.set(roomId, []);
203
+ }
204
+ catch (error) {
205
+ const err = error;
206
+ throw new Error(`Failed to flush events: ${err.message}`);
207
+ }
208
+ }
209
+ /**
210
+ * 恢复房间状态
211
+ */
212
+ async recoverRoom(roomId) {
213
+ try {
214
+ // 1. 加载快照
215
+ const snapshotData = await this.redis.client.hgetall(`gw:room:${roomId}:snapshot`);
216
+ if (!snapshotData || !snapshotData.state) {
217
+ this.logger.warn(`No snapshot found for room ${roomId}`);
218
+ return null;
219
+ }
220
+ let state = JSON.parse(snapshotData.state);
221
+ let version = parseInt(snapshotData.version || '0');
222
+ this.logger.log(`Loaded snapshot for room ${roomId}, version ${version}`);
223
+ // 2. 应用增量事件
224
+ const eventStrings = await this.redis.client.lrange(`gw:room:${roomId}:events`, 0, -1);
225
+ if (eventStrings.length > 0) {
226
+ this.logger.log(`Applying ${eventStrings.length} incremental events for room ${roomId}`);
227
+ for (const eventStr of eventStrings) {
228
+ const event = JSON.parse(eventStr);
229
+ // 只应用快照之后的事件
230
+ if (event.version > version) {
231
+ state = this.applyEvent(state, event);
232
+ version = event.version;
233
+ }
234
+ }
235
+ this.logger.log(`Applied events, final version ${version} for room ${roomId}`);
236
+ }
237
+ return {
238
+ roomId,
239
+ state,
240
+ version,
241
+ timestamp: parseInt(snapshotData.timestamp || Date.now().toString()),
242
+ workerId: snapshotData.workerId || 'unknown',
243
+ };
244
+ }
245
+ catch (error) {
246
+ const err = error;
247
+ this.logger.error(`Failed to recover room ${roomId}: ${err.message}`, err.stack);
248
+ return null;
249
+ }
250
+ }
251
+ /**
252
+ * 应用事件到状态
253
+ */
254
+ applyEvent(state, event) {
255
+ // 根据事件类型应用状态变更
256
+ // 这里需要根据具体的游戏逻辑实现
257
+ // 默认:如果事件有data字段,直接合并到state
258
+ if (event.data) {
259
+ return { ...state, ...event.data };
260
+ }
261
+ return state;
262
+ }
263
+ /**
264
+ * 清理房间持久化数据
265
+ */
266
+ async cleanupRoomData(roomId) {
267
+ try {
268
+ await this.redis.client.del(`gw:room:${roomId}:snapshot`);
269
+ await this.redis.client.del(`gw:room:${roomId}:events`);
270
+ this.logger.log(`Cleaned up persistence data for room ${roomId}`);
271
+ }
272
+ catch (error) {
273
+ const err = error;
274
+ this.logger.error(`Failed to cleanup room data ${roomId}: ${err.message}`);
275
+ }
276
+ }
277
+ /**
278
+ * 获取持久化统计信息
279
+ */
280
+ getStats() {
281
+ const bufferedEvents = Array.from(this.eventBuffer.values()).reduce((sum, buffer) => sum + buffer.length, 0);
282
+ return {
283
+ activeRooms: this.persistenceTasks.size,
284
+ bufferedEvents,
285
+ options: this.options,
286
+ };
287
+ }
288
+ /**
289
+ * 模块销毁时清理
290
+ */
291
+ async onModuleDestroy() {
292
+ this.logger.log('Shutting down persistence service...');
293
+ // 停止所有持久化任务
294
+ const roomIds = Array.from(this.persistenceTasks.keys());
295
+ for (const roomId of roomIds) {
296
+ await this.stopPersistence(roomId);
297
+ }
298
+ this.logger.log('Persistence service shut down');
299
+ }
300
+ };
301
+ exports.RoomPersistenceService = RoomPersistenceService;
302
+ exports.RoomPersistenceService = RoomPersistenceService = RoomPersistenceService_1 = __decorate([
303
+ (0, common_1.Injectable)(),
304
+ __metadata("design:paramtypes", [redis_service_js_1.RedisService,
305
+ config_service_js_1.ConfigService])
306
+ ], RoomPersistenceService);
307
+ //# sourceMappingURL=room-persistence.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-persistence.service.js","sourceRoot":"","sources":["../../../src/room/room-persistence.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { RoomManagerService } from './room-manager.service';
3
+ import { RedisService } from '../redis/redis.service';
4
+ /**
5
+ * 房间注册服务
6
+ * 在模块初始化时注册所有房间类型
7
+ */
8
+ export declare class RoomRegistryService implements OnModuleInit {
9
+ private readonly roomManager;
10
+ private readonly redisService;
11
+ private readonly logger;
12
+ constructor(roomManager: RoomManagerService, redisService: RedisService);
13
+ onModuleInit(): Promise<void>;
14
+ private registerRoomTypes;
15
+ }
16
+ //# sourceMappingURL=room-registry.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-registry.service.d.ts","sourceRoot":"","sources":["../../../src/room/room-registry.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAU,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD;;;GAGG;AACH,qBACa,mBAAoB,YAAW,YAAY;IAIpD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJ/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;gBAG5C,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,YAAY;IAGvC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC,OAAO,CAAC,iBAAiB;CAU1B"}
@@ -0,0 +1,60 @@
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 RoomRegistryService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.RoomRegistryService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const room_manager_service_1 = require("./room-manager.service");
16
+ const redis_service_1 = require("../redis/redis.service");
17
+ const rooms_1 = require("./rooms");
18
+ /**
19
+ * 房间注册服务
20
+ * 在模块初始化时注册所有房间类型
21
+ */
22
+ let RoomRegistryService = RoomRegistryService_1 = class RoomRegistryService {
23
+ roomManager;
24
+ redisService;
25
+ logger = new common_1.Logger(RoomRegistryService_1.name);
26
+ constructor(roomManager, redisService) {
27
+ this.roomManager = roomManager;
28
+ this.redisService = redisService;
29
+ }
30
+ async onModuleInit() {
31
+ // 1. 注册所有房间类型
32
+ this.registerRoomTypes();
33
+ // 2. 获取已注册的类型并注册 Worker
34
+ const gameTypes = this.roomManager.getRegisteredGameTypes();
35
+ this.logger.log(`About to register worker with gameTypes: ${gameTypes.join(', ')}`);
36
+ try {
37
+ await this.redisService.registerWorker(gameTypes);
38
+ this.logger.log('Worker registration completed');
39
+ }
40
+ catch (error) {
41
+ this.logger.error('Failed to register worker:', error);
42
+ throw error;
43
+ }
44
+ }
45
+ registerRoomTypes() {
46
+ // 注册内置房间类型
47
+ this.roomManager.registerRoomType('echo', rooms_1.EchoRoom);
48
+ // 用户可以在这里注册自己的房间类型
49
+ // this.roomManager.registerRoomType('poker', PokerRoom);
50
+ const gameTypes = this.roomManager.getRegisteredGameTypes();
51
+ this.logger.log(`Room types registered: ${gameTypes.join(', ')}`);
52
+ }
53
+ };
54
+ exports.RoomRegistryService = RoomRegistryService;
55
+ exports.RoomRegistryService = RoomRegistryService = RoomRegistryService_1 = __decorate([
56
+ (0, common_1.Injectable)(),
57
+ __metadata("design:paramtypes", [room_manager_service_1.RoomManagerService,
58
+ redis_service_1.RedisService])
59
+ ], RoomRegistryService);
60
+ //# sourceMappingURL=room-registry.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-registry.service.js","sourceRoot":"","sources":["../../../src/room/room-registry.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAkE;AAClE,iEAA4D;AAC5D,0DAAsD;AACtD,mCAAmC;AAEnC;;;GAGG;AAEI,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAIX;IACA;IAJF,MAAM,GAAG,IAAI,eAAM,CAAC,qBAAmB,CAAC,IAAI,CAAC,CAAC;IAE/D,YACmB,WAA+B,EAC/B,YAA0B;QAD1B,gBAAW,GAAX,WAAW,CAAoB;QAC/B,iBAAY,GAAZ,YAAY,CAAc;IAC1C,CAAC;IAEJ,KAAK,CAAC,YAAY;QAChB,cAAc;QACd,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,wBAAwB;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,sBAAsB,EAAE,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,4CAA4C,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,WAAW;QACX,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,gBAAQ,CAAC,CAAC;QAEpD,mBAAmB;QACnB,yDAAyD;QAEzD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,sBAAsB,EAAE,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;CACF,CAAA;AAlCY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAKqB,yCAAkB;QACjB,4BAAY;GALlC,mBAAmB,CAkC/B"}
@@ -0,0 +1,15 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { AuthHandler } from '../config/worker.config';
3
+ export declare class RoomModule {
4
+ /**
5
+ * 创建 RoomModule,支持自定义认证处理器
6
+ * @param authHandler 可选的自定义认证处理器
7
+ */
8
+ static forRoot(authHandler?: AuthHandler): DynamicModule;
9
+ }
10
+ export { GameRoom } from './game-room';
11
+ export { ClientProxy } from './client-proxy';
12
+ export { RoomManagerService } from './room-manager.service';
13
+ export { MessageHandlerService } from './message-handler.service';
14
+ export { EchoRoom } from './rooms';
15
+ //# sourceMappingURL=room.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.module.d.ts","sourceRoot":"","sources":["../../../src/room/room.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO/D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,qBAEa,UAAU;IACrB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,aAAa;CAgBzD;AAED,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,55 @@
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 RoomModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EchoRoom = exports.MessageHandlerService = exports.RoomManagerService = exports.ClientProxy = exports.GameRoom = exports.RoomModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const room_manager_service_1 = require("./room-manager.service");
13
+ const message_handler_service_1 = require("./message-handler.service");
14
+ const room_registry_service_1 = require("./room-registry.service");
15
+ const room_persistence_service_1 = require("./room-persistence.service");
16
+ const auth_module_1 = require("../auth/auth.module");
17
+ const circuit_breaker_module_1 = require("../circuit-breaker/circuit-breaker.module");
18
+ let RoomModule = RoomModule_1 = class RoomModule {
19
+ /**
20
+ * 创建 RoomModule,支持自定义认证处理器
21
+ * @param authHandler 可选的自定义认证处理器
22
+ */
23
+ static forRoot(authHandler) {
24
+ return {
25
+ module: RoomModule_1,
26
+ imports: [
27
+ auth_module_1.AuthModule.forRoot(authHandler),
28
+ circuit_breaker_module_1.CircuitBreakerModule,
29
+ ],
30
+ providers: [
31
+ room_manager_service_1.RoomManagerService,
32
+ message_handler_service_1.MessageHandlerService,
33
+ room_registry_service_1.RoomRegistryService,
34
+ room_persistence_service_1.RoomPersistenceService,
35
+ ],
36
+ exports: [room_manager_service_1.RoomManagerService, room_persistence_service_1.RoomPersistenceService],
37
+ };
38
+ }
39
+ };
40
+ exports.RoomModule = RoomModule;
41
+ exports.RoomModule = RoomModule = RoomModule_1 = __decorate([
42
+ (0, common_1.Global)(),
43
+ (0, common_1.Module)({})
44
+ ], RoomModule);
45
+ var game_room_1 = require("./game-room");
46
+ Object.defineProperty(exports, "GameRoom", { enumerable: true, get: function () { return game_room_1.GameRoom; } });
47
+ var client_proxy_1 = require("./client-proxy");
48
+ Object.defineProperty(exports, "ClientProxy", { enumerable: true, get: function () { return client_proxy_1.ClientProxy; } });
49
+ var room_manager_service_2 = require("./room-manager.service");
50
+ Object.defineProperty(exports, "RoomManagerService", { enumerable: true, get: function () { return room_manager_service_2.RoomManagerService; } });
51
+ var message_handler_service_2 = require("./message-handler.service");
52
+ Object.defineProperty(exports, "MessageHandlerService", { enumerable: true, get: function () { return message_handler_service_2.MessageHandlerService; } });
53
+ var rooms_1 = require("./rooms");
54
+ Object.defineProperty(exports, "EchoRoom", { enumerable: true, get: function () { return rooms_1.EchoRoom; } });
55
+ //# sourceMappingURL=room.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.module.js","sourceRoot":"","sources":["../../../src/room/room.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA+D;AAC/D,iEAA4D;AAC5D,uEAAkE;AAClE,mEAA8D;AAC9D,yEAAoE;AACpE,qDAAiD;AACjD,sFAAiF;AAK1E,IAAM,UAAU,kBAAhB,MAAM,UAAU;IACrB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,WAAyB;QACtC,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,OAAO,EAAE;gBACP,wBAAU,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC/B,6CAAoB;aACrB;YACD,SAAS,EAAE;gBACT,yCAAkB;gBAClB,+CAAqB;gBACrB,2CAAmB;gBACnB,iDAAsB;aACvB;YACD,OAAO,EAAE,CAAC,yCAAkB,EAAE,iDAAsB,CAAC;SACtD,CAAC;IACJ,CAAC;CACF,CAAA;AArBY,gCAAU;qBAAV,UAAU;IAFtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,UAAU,CAqBtB;AAED,yCAAuC;AAA9B,qGAAA,QAAQ,OAAA;AACjB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AACpB,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAC3B,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA"}
@@ -0,0 +1,18 @@
1
+ import { GameRoom } from '../game-room';
2
+ import { ClientProxy } from '../client-proxy';
3
+ /**
4
+ * EchoRoom - 示例游戏房间
5
+ * 简单地将收到的消息广播给房间内所有玩家
6
+ */
7
+ export declare class EchoRoom extends GameRoom {
8
+ private messageHistory;
9
+ private maxHistorySize;
10
+ onCreate(options: Record<string, unknown>): Promise<void>;
11
+ onAuth(client: ClientProxy, options: Record<string, unknown>): Promise<boolean>;
12
+ onJoin(client: ClientProxy, options: Record<string, unknown>): Promise<void>;
13
+ onLeave(client: ClientProxy, reason: string): Promise<void>;
14
+ onMessage(client: ClientProxy, msgType: string, payload: unknown): Promise<void>;
15
+ onDispose(): Promise<void>;
16
+ private handleChat;
17
+ }
18
+ //# sourceMappingURL=echo-room.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echo-room.d.ts","sourceRoot":"","sources":["../../../../src/room/rooms/echo-room.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C;;;GAGG;AACH,qBAAa,QAAS,SAAQ,QAAQ;IACpC,OAAO,CAAC,cAAc,CAAqE;IAC3F,OAAO,CAAC,cAAc,CAAO;IAEvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAM/E,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5E,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3D,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhF,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;YAKlB,UAAU;CAgBzB"}