@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.
- package/README.md +122 -0
- package/dist/src/admin/admin.controller.d.ts +275 -0
- package/dist/src/admin/admin.controller.d.ts.map +1 -0
- package/dist/src/admin/admin.controller.js +296 -0
- package/dist/src/admin/admin.controller.js.map +1 -0
- package/dist/src/admin/admin.module.d.ts +3 -0
- package/dist/src/admin/admin.module.d.ts.map +1 -0
- package/dist/src/admin/admin.module.js +35 -0
- package/dist/src/admin/admin.module.js.map +1 -0
- package/dist/src/admin/admin.service.d.ts +282 -0
- package/dist/src/admin/admin.service.d.ts.map +1 -0
- package/dist/src/admin/admin.service.js +508 -0
- package/dist/src/admin/admin.service.js.map +1 -0
- package/dist/src/auth/auth.module.d.ts +10 -0
- package/dist/src/auth/auth.module.d.ts.map +1 -0
- package/dist/src/auth/auth.module.js +37 -0
- package/dist/src/auth/auth.module.js.map +1 -0
- package/dist/src/auth/auth.service.d.ts +21 -0
- package/dist/src/auth/auth.service.d.ts.map +1 -0
- package/dist/src/auth/auth.service.js +69 -0
- package/dist/src/auth/auth.service.js.map +1 -0
- package/dist/src/circuit-breaker/circuit-breaker.module.d.ts +3 -0
- package/dist/src/circuit-breaker/circuit-breaker.module.d.ts.map +1 -0
- package/dist/src/circuit-breaker/circuit-breaker.module.js +24 -0
- package/dist/src/circuit-breaker/circuit-breaker.module.js.map +1 -0
- package/dist/src/circuit-breaker/circuit-breaker.service.d.ts +89 -0
- package/dist/src/circuit-breaker/circuit-breaker.service.d.ts.map +1 -0
- package/dist/src/circuit-breaker/circuit-breaker.service.js +207 -0
- package/dist/src/circuit-breaker/circuit-breaker.service.js.map +1 -0
- package/dist/src/config/config.module.d.ts +3 -0
- package/dist/src/config/config.module.d.ts.map +1 -0
- package/dist/src/config/config.module.js +22 -0
- package/dist/src/config/config.module.js.map +1 -0
- package/dist/src/config/config.service.d.ts +19 -0
- package/dist/src/config/config.service.d.ts.map +1 -0
- package/dist/src/config/config.service.js +58 -0
- package/dist/src/config/config.service.js.map +1 -0
- package/dist/src/config/worker.config.d.ts +82 -0
- package/dist/src/config/worker.config.d.ts.map +1 -0
- package/dist/src/config/worker.config.js +35 -0
- package/dist/src/config/worker.config.js.map +1 -0
- package/dist/src/index.d.ts +48 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +108 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lifecycle/graceful-shutdown.service.d.ts +71 -0
- package/dist/src/lifecycle/graceful-shutdown.service.d.ts.map +1 -0
- package/dist/src/lifecycle/graceful-shutdown.service.js +221 -0
- package/dist/src/lifecycle/graceful-shutdown.service.js.map +1 -0
- package/dist/src/lifecycle/index.d.ts +2 -0
- package/dist/src/lifecycle/index.d.ts.map +1 -0
- package/dist/src/lifecycle/index.js +18 -0
- package/dist/src/lifecycle/index.js.map +1 -0
- package/dist/src/main.d.ts +2 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +54 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/metrics/metrics.controller.d.ts +15 -0
- package/dist/src/metrics/metrics.controller.d.ts.map +1 -0
- package/dist/src/metrics/metrics.controller.js +44 -0
- package/dist/src/metrics/metrics.controller.js.map +1 -0
- package/dist/src/metrics/metrics.module.d.ts +7 -0
- package/dist/src/metrics/metrics.module.d.ts.map +1 -0
- package/dist/src/metrics/metrics.module.js +28 -0
- package/dist/src/metrics/metrics.module.js.map +1 -0
- package/dist/src/metrics/metrics.service.d.ts +65 -0
- package/dist/src/metrics/metrics.service.d.ts.map +1 -0
- package/dist/src/metrics/metrics.service.js +306 -0
- package/dist/src/metrics/metrics.service.js.map +1 -0
- package/dist/src/migration/migration.module.d.ts +3 -0
- package/dist/src/migration/migration.module.d.ts.map +1 -0
- package/dist/src/migration/migration.module.js +30 -0
- package/dist/src/migration/migration.module.js.map +1 -0
- package/dist/src/migration/migration.service.d.ts +68 -0
- package/dist/src/migration/migration.service.d.ts.map +1 -0
- package/dist/src/migration/migration.service.js +295 -0
- package/dist/src/migration/migration.service.js.map +1 -0
- package/dist/src/migration/room-migration.service.d.ts +92 -0
- package/dist/src/migration/room-migration.service.d.ts.map +1 -0
- package/dist/src/migration/room-migration.service.js +297 -0
- package/dist/src/migration/room-migration.service.js.map +1 -0
- package/dist/src/redis/redis.module.d.ts +3 -0
- package/dist/src/redis/redis.module.d.ts.map +1 -0
- package/dist/src/redis/redis.module.js +22 -0
- package/dist/src/redis/redis.module.js.map +1 -0
- package/dist/src/redis/redis.service.d.ts +68 -0
- package/dist/src/redis/redis.service.d.ts.map +1 -0
- package/dist/src/redis/redis.service.js +260 -0
- package/dist/src/redis/redis.service.js.map +1 -0
- package/dist/src/room/client-proxy.d.ts +43 -0
- package/dist/src/room/client-proxy.d.ts.map +1 -0
- package/dist/src/room/client-proxy.js +91 -0
- package/dist/src/room/client-proxy.js.map +1 -0
- package/dist/src/room/game-room.d.ts +243 -0
- package/dist/src/room/game-room.d.ts.map +1 -0
- package/dist/src/room/game-room.js +434 -0
- package/dist/src/room/game-room.js.map +1 -0
- package/dist/src/room/message-handler.service.d.ts +70 -0
- package/dist/src/room/message-handler.service.d.ts.map +1 -0
- package/dist/src/room/message-handler.service.js +541 -0
- package/dist/src/room/message-handler.service.js.map +1 -0
- package/dist/src/room/room-manager.service.d.ts +132 -0
- package/dist/src/room/room-manager.service.d.ts.map +1 -0
- package/dist/src/room/room-manager.service.js +571 -0
- package/dist/src/room/room-manager.service.js.map +1 -0
- package/dist/src/room/room-persistence.service.d.ts +101 -0
- package/dist/src/room/room-persistence.service.d.ts.map +1 -0
- package/dist/src/room/room-persistence.service.js +307 -0
- package/dist/src/room/room-persistence.service.js.map +1 -0
- package/dist/src/room/room-registry.service.d.ts +16 -0
- package/dist/src/room/room-registry.service.d.ts.map +1 -0
- package/dist/src/room/room-registry.service.js +60 -0
- package/dist/src/room/room-registry.service.js.map +1 -0
- package/dist/src/room/room.module.d.ts +15 -0
- package/dist/src/room/room.module.d.ts.map +1 -0
- package/dist/src/room/room.module.js +55 -0
- package/dist/src/room/room.module.js.map +1 -0
- package/dist/src/room/rooms/echo-room.d.ts +18 -0
- package/dist/src/room/rooms/echo-room.d.ts.map +1 -0
- package/dist/src/room/rooms/echo-room.js +85 -0
- package/dist/src/room/rooms/echo-room.js.map +1 -0
- package/dist/src/room/rooms/index.d.ts +2 -0
- package/dist/src/room/rooms/index.d.ts.map +1 -0
- package/dist/src/room/rooms/index.js +6 -0
- package/dist/src/room/rooms/index.js.map +1 -0
- package/dist/src/worker.module.d.ts +10 -0
- package/dist/src/worker.module.d.ts.map +1 -0
- package/dist/src/worker.module.js +46 -0
- package/dist/src/worker.module.js.map +1 -0
- package/dist/test/circuit-breaker/circuit-breaker.service.spec.d.ts +2 -0
- package/dist/test/circuit-breaker/circuit-breaker.service.spec.d.ts.map +1 -0
- package/dist/test/circuit-breaker/circuit-breaker.service.spec.js +220 -0
- package/dist/test/circuit-breaker/circuit-breaker.service.spec.js.map +1 -0
- package/dist/test/integration/admin-api.spec.d.ts +2 -0
- package/dist/test/integration/admin-api.spec.d.ts.map +1 -0
- package/dist/test/integration/admin-api.spec.js +246 -0
- package/dist/test/integration/admin-api.spec.js.map +1 -0
- package/dist/test/migration/game-room-migration.spec.d.ts +2 -0
- package/dist/test/migration/game-room-migration.spec.d.ts.map +1 -0
- package/dist/test/migration/game-room-migration.spec.js +222 -0
- package/dist/test/migration/game-room-migration.spec.js.map +1 -0
- package/dist/test/room/client-proxy.spec.d.ts +2 -0
- package/dist/test/room/client-proxy.spec.d.ts.map +1 -0
- package/dist/test/room/client-proxy.spec.js +117 -0
- package/dist/test/room/client-proxy.spec.js.map +1 -0
- package/dist/test/room/game-room.spec.d.ts +2 -0
- package/dist/test/room/game-room.spec.d.ts.map +1 -0
- package/dist/test/room/game-room.spec.js +219 -0
- package/dist/test/room/game-room.spec.js.map +1 -0
- package/dist/test/room/room-manager.service.spec.d.ts +2 -0
- package/dist/test/room/room-manager.service.spec.d.ts.map +1 -0
- package/dist/test/room/room-manager.service.spec.js +280 -0
- package/dist/test/room/room-manager.service.spec.js.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +56 -0
- package/dist/test/setup.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @roomkit/worker - Worker Server for Gateway-Worker Framework
|
|
4
|
+
*
|
|
5
|
+
* Creates a game logic worker that handles room management
|
|
6
|
+
* and game state, communicating with gateways via Redis.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { createWorker, GameRoom } from '@roomkit/worker';
|
|
11
|
+
*
|
|
12
|
+
* class PokerRoom extends GameRoom {
|
|
13
|
+
* onCreate(options) { }
|
|
14
|
+
* onJoin(client, options) { }
|
|
15
|
+
* onMessage(client, msgId, payload) { }
|
|
16
|
+
* onLeave(client, reason) { }
|
|
17
|
+
* onDispose() { }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* const worker = await createWorker({
|
|
21
|
+
* redis: 'redis://localhost:6379',
|
|
22
|
+
* rooms: { 'poker': PokerRoom },
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* await worker.listen();
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
31
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
33
|
+
}
|
|
34
|
+
Object.defineProperty(o, k2, desc);
|
|
35
|
+
}) : (function(o, m, k, k2) {
|
|
36
|
+
if (k2 === undefined) k2 = k;
|
|
37
|
+
o[k2] = m[k];
|
|
38
|
+
}));
|
|
39
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
40
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.WorkerModule = exports.ClientProxy = exports.GameRoom = void 0;
|
|
44
|
+
exports.createWorker = createWorker;
|
|
45
|
+
const core_1 = require("@nestjs/core");
|
|
46
|
+
const worker_module_1 = require("./worker.module");
|
|
47
|
+
const room_manager_service_1 = require("./room/room-manager.service");
|
|
48
|
+
const worker_config_1 = require("./config/worker.config");
|
|
49
|
+
const uuid_1 = require("uuid");
|
|
50
|
+
/**
|
|
51
|
+
* Create a Worker server instance
|
|
52
|
+
*/
|
|
53
|
+
async function createWorker(config) {
|
|
54
|
+
// Normalize configuration
|
|
55
|
+
const workerId = config.id || `worker-${(0, uuid_1.v4)().slice(0, 8)}`;
|
|
56
|
+
const redisConfig = (0, worker_config_1.normalizeRedisConfig)(config.redis);
|
|
57
|
+
const circuitBreakerConfig = { ...worker_config_1.DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config.circuitBreaker };
|
|
58
|
+
const adminConfig = { ...worker_config_1.DEFAULT_ADMIN_CONFIG, ...config.admin };
|
|
59
|
+
// Set environment variables for the module
|
|
60
|
+
// 使用 GW_ 前缀,与 ConfigService 保持一致
|
|
61
|
+
process.env.GW_WORKER_ID = workerId;
|
|
62
|
+
process.env.GW_REDIS_HOST = redisConfig.host || 'localhost';
|
|
63
|
+
process.env.GW_REDIS_PORT = String(redisConfig.port || 6379);
|
|
64
|
+
if (redisConfig.password)
|
|
65
|
+
process.env.GW_REDIS_PASSWORD = redisConfig.password;
|
|
66
|
+
process.env.GW_WORKER_ADMIN_PORT = String(adminConfig.port);
|
|
67
|
+
process.env.GW_CIRCUIT_FAILURE_THRESHOLD = String(circuitBreakerConfig.failureThreshold);
|
|
68
|
+
process.env.GW_CIRCUIT_SUCCESS_THRESHOLD = String(circuitBreakerConfig.successThreshold);
|
|
69
|
+
process.env.GW_CIRCUIT_OPEN_TIMEOUT = String(circuitBreakerConfig.openTimeout);
|
|
70
|
+
// Create NestJS application with custom auth handler
|
|
71
|
+
const app = await core_1.NestFactory.create(worker_module_1.WorkerModule.forRoot(config.auth), {
|
|
72
|
+
logger: ['error', 'warn', 'log', 'debug'],
|
|
73
|
+
});
|
|
74
|
+
// Register custom room types
|
|
75
|
+
const roomManager = app.get(room_manager_service_1.RoomManagerService);
|
|
76
|
+
if (config.rooms) {
|
|
77
|
+
for (const [gameType, RoomClass] of Object.entries(config.rooms)) {
|
|
78
|
+
roomManager.registerRoomType(gameType, RoomClass);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const registeredTypes = roomManager.getRegisteredGameTypes();
|
|
82
|
+
return {
|
|
83
|
+
id: workerId,
|
|
84
|
+
adminPort: adminConfig.port,
|
|
85
|
+
gameTypes: registeredTypes,
|
|
86
|
+
async listen() {
|
|
87
|
+
if (adminConfig.enabled) {
|
|
88
|
+
await app.listen(adminConfig.port);
|
|
89
|
+
console.log(`[Worker] Admin API started on port ${adminConfig.port}`);
|
|
90
|
+
}
|
|
91
|
+
console.log(`[Worker] Started, id: ${workerId}`);
|
|
92
|
+
console.log(`[Worker] Registered game types: ${registeredTypes.join(', ')}`);
|
|
93
|
+
},
|
|
94
|
+
async close() {
|
|
95
|
+
await app.close();
|
|
96
|
+
console.log(`[Worker] Server stopped`);
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Re-export core classes for user extension
|
|
101
|
+
var game_room_1 = require("./room/game-room");
|
|
102
|
+
Object.defineProperty(exports, "GameRoom", { enumerable: true, get: function () { return game_room_1.GameRoom; } });
|
|
103
|
+
var client_proxy_1 = require("./room/client-proxy");
|
|
104
|
+
Object.defineProperty(exports, "ClientProxy", { enumerable: true, get: function () { return client_proxy_1.ClientProxy; } });
|
|
105
|
+
__exportStar(require("./config/worker.config"), exports);
|
|
106
|
+
var worker_module_2 = require("./worker.module");
|
|
107
|
+
Object.defineProperty(exports, "WorkerModule", { enumerable: true, get: function () { return worker_module_2.WorkerModule; } });
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker优雅关闭服务
|
|
3
|
+
*
|
|
4
|
+
* 功能:
|
|
5
|
+
* 1. 标记节点为draining状态
|
|
6
|
+
* 2. 等待现有房间处理完成
|
|
7
|
+
* 3. 保存房间快照
|
|
8
|
+
* 4. 清理资源
|
|
9
|
+
*/
|
|
10
|
+
import { OnModuleDestroy } from '@nestjs/common';
|
|
11
|
+
import { RedisService } from '../redis/redis.service.js';
|
|
12
|
+
import { RoomManagerService } from '../room/room-manager.service.js';
|
|
13
|
+
import { ConfigService } from '../config/config.service.js';
|
|
14
|
+
export interface GracefulShutdownOptions {
|
|
15
|
+
/** 优雅关闭超时时间(毫秒) */
|
|
16
|
+
timeout?: number;
|
|
17
|
+
/** 是否保存房间快照 */
|
|
18
|
+
saveSnapshots?: boolean;
|
|
19
|
+
/** 是否强制关闭 */
|
|
20
|
+
force?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare class GracefulShutdownService implements OnModuleDestroy {
|
|
23
|
+
private readonly redis;
|
|
24
|
+
private readonly roomManager;
|
|
25
|
+
private readonly config;
|
|
26
|
+
private readonly logger;
|
|
27
|
+
private isShuttingDown;
|
|
28
|
+
private shutdownPromise?;
|
|
29
|
+
constructor(redis: RedisService, roomManager: RoomManagerService, config: ConfigService);
|
|
30
|
+
/**
|
|
31
|
+
* 检查是否正在关闭
|
|
32
|
+
*/
|
|
33
|
+
get isInShutdown(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* 开始优雅关闭流程
|
|
36
|
+
*/
|
|
37
|
+
startShutdown(options?: GracefulShutdownOptions): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* 执行关闭流程
|
|
40
|
+
*/
|
|
41
|
+
private _executeShutdown;
|
|
42
|
+
/**
|
|
43
|
+
* 设置节点为draining状态
|
|
44
|
+
*/
|
|
45
|
+
private setDrainingStatus;
|
|
46
|
+
/**
|
|
47
|
+
* 等待所有房间结束
|
|
48
|
+
*/
|
|
49
|
+
private waitForRoomsToFinish;
|
|
50
|
+
/**
|
|
51
|
+
* 保存所有房间快照
|
|
52
|
+
*/
|
|
53
|
+
private saveAllRoomSnapshots;
|
|
54
|
+
/**
|
|
55
|
+
* 保存单个房间快照
|
|
56
|
+
*/
|
|
57
|
+
private saveRoomSnapshot;
|
|
58
|
+
/**
|
|
59
|
+
* 清理资源
|
|
60
|
+
*/
|
|
61
|
+
private cleanup;
|
|
62
|
+
/**
|
|
63
|
+
* 模块销毁时的钩子
|
|
64
|
+
*/
|
|
65
|
+
onModuleDestroy(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* 工具:Sleep
|
|
68
|
+
*/
|
|
69
|
+
private sleep;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=graceful-shutdown.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graceful-shutdown.service.d.ts","sourceRoot":"","sources":["../../../src/lifecycle/graceful-shutdown.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAsB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBACa,uBAAwB,YAAW,eAAe;IAM3D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAgB;gBAGrB,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,kBAAkB,EAC/B,MAAM,EAAE,aAAa;IAGxC;;OAEG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;OAEG;IACG,aAAa,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBzE;;OAEG;YACW,gBAAgB;IA6C9B;;OAEG;YACW,iBAAiB;IA2B/B;;OAEG;YACW,oBAAoB;IAoBlC;;OAEG;YACW,oBAAoB;IAwBlC;;OAEG;YACW,gBAAgB;IAmB9B;;OAEG;YACW,OAAO;IA0BrB;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtC;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Worker优雅关闭服务
|
|
4
|
+
*
|
|
5
|
+
* 功能:
|
|
6
|
+
* 1. 标记节点为draining状态
|
|
7
|
+
* 2. 等待现有房间处理完成
|
|
8
|
+
* 3. 保存房间快照
|
|
9
|
+
* 4. 清理资源
|
|
10
|
+
*/
|
|
11
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
12
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
13
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
14
|
+
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;
|
|
15
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
16
|
+
};
|
|
17
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
18
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
19
|
+
};
|
|
20
|
+
var GracefulShutdownService_1;
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.GracefulShutdownService = void 0;
|
|
23
|
+
const common_1 = require("@nestjs/common");
|
|
24
|
+
const redis_service_js_1 = require("../redis/redis.service.js");
|
|
25
|
+
const room_manager_service_js_1 = require("../room/room-manager.service.js");
|
|
26
|
+
const config_service_js_1 = require("../config/config.service.js");
|
|
27
|
+
let GracefulShutdownService = GracefulShutdownService_1 = class GracefulShutdownService {
|
|
28
|
+
redis;
|
|
29
|
+
roomManager;
|
|
30
|
+
config;
|
|
31
|
+
logger = new common_1.Logger(GracefulShutdownService_1.name);
|
|
32
|
+
isShuttingDown = false;
|
|
33
|
+
shutdownPromise;
|
|
34
|
+
constructor(redis, roomManager, config) {
|
|
35
|
+
this.redis = redis;
|
|
36
|
+
this.roomManager = roomManager;
|
|
37
|
+
this.config = config;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 检查是否正在关闭
|
|
41
|
+
*/
|
|
42
|
+
get isInShutdown() {
|
|
43
|
+
return this.isShuttingDown;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 开始优雅关闭流程
|
|
47
|
+
*/
|
|
48
|
+
async startShutdown(options = {}) {
|
|
49
|
+
if (this.isShuttingDown) {
|
|
50
|
+
this.logger.warn('Shutdown already in progress');
|
|
51
|
+
return this.shutdownPromise;
|
|
52
|
+
}
|
|
53
|
+
this.isShuttingDown = true;
|
|
54
|
+
const { timeout = 60000, saveSnapshots = true, force = false, } = options;
|
|
55
|
+
this.shutdownPromise = this._executeShutdown(timeout, saveSnapshots, force);
|
|
56
|
+
return this.shutdownPromise;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 执行关闭流程
|
|
60
|
+
*/
|
|
61
|
+
async _executeShutdown(timeout, saveSnapshots, force) {
|
|
62
|
+
const workerId = this.config.workerId;
|
|
63
|
+
this.logger.log(`Starting graceful shutdown for worker ${workerId}`);
|
|
64
|
+
try {
|
|
65
|
+
// 1. 标记为draining状态(不接受新房间)
|
|
66
|
+
await this.setDrainingStatus();
|
|
67
|
+
if (force) {
|
|
68
|
+
// 强制关闭:直接保存并退出
|
|
69
|
+
this.logger.warn('Force shutdown requested');
|
|
70
|
+
if (saveSnapshots) {
|
|
71
|
+
await this.saveAllRoomSnapshots();
|
|
72
|
+
}
|
|
73
|
+
await this.cleanup();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// 2. 等待现有房间结束(带超时)
|
|
77
|
+
const roomsFinished = await this.waitForRoomsToFinish(timeout);
|
|
78
|
+
if (!roomsFinished) {
|
|
79
|
+
this.logger.warn(`Shutdown timeout after ${timeout}ms, ${this.roomManager.getRoomCount()} rooms remaining`);
|
|
80
|
+
}
|
|
81
|
+
// 3. 保存剩余房间快照
|
|
82
|
+
if (saveSnapshots) {
|
|
83
|
+
await this.saveAllRoomSnapshots();
|
|
84
|
+
}
|
|
85
|
+
// 4. 清理资源
|
|
86
|
+
await this.cleanup();
|
|
87
|
+
this.logger.log('Graceful shutdown completed');
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const err = error;
|
|
91
|
+
this.logger.error(`Error during graceful shutdown: ${err.message}`, err.stack);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 设置节点为draining状态
|
|
97
|
+
*/
|
|
98
|
+
async setDrainingStatus() {
|
|
99
|
+
const workerId = this.config.workerId;
|
|
100
|
+
try {
|
|
101
|
+
// 更新Worker状态为draining
|
|
102
|
+
await this.redis.client.hset(`gw:worker:${workerId}`, 'status', 'draining');
|
|
103
|
+
await this.redis.client.hset(`gw:worker:${workerId}`, 'drainingStartedAt', Date.now().toString());
|
|
104
|
+
// 延长TTL,确保draining期间不会过期
|
|
105
|
+
await this.redis.client.expire(`gw:worker:${workerId}`, 120);
|
|
106
|
+
this.logger.log(`Worker ${workerId} marked as draining`);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
const err = error;
|
|
110
|
+
this.logger.error(`Failed to set draining status: ${err.message}`);
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 等待所有房间结束
|
|
116
|
+
*/
|
|
117
|
+
async waitForRoomsToFinish(timeout) {
|
|
118
|
+
const startTime = Date.now();
|
|
119
|
+
const checkInterval = 1000; // 每秒检查一次
|
|
120
|
+
while (this.roomManager.getRoomCount() > 0) {
|
|
121
|
+
const elapsed = Date.now() - startTime;
|
|
122
|
+
if (elapsed >= timeout) {
|
|
123
|
+
return false; // 超时
|
|
124
|
+
}
|
|
125
|
+
const remainingRooms = this.roomManager.getRoomCount();
|
|
126
|
+
this.logger.log(`Waiting for ${remainingRooms} rooms to finish... (${Math.floor(elapsed / 1000)}s elapsed)`);
|
|
127
|
+
await this.sleep(checkInterval);
|
|
128
|
+
}
|
|
129
|
+
return true; // 所有房间已结束
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 保存所有房间快照
|
|
133
|
+
*/
|
|
134
|
+
async saveAllRoomSnapshots() {
|
|
135
|
+
const rooms = this.roomManager.getAllRooms();
|
|
136
|
+
const roomCount = rooms.size;
|
|
137
|
+
if (roomCount === 0) {
|
|
138
|
+
this.logger.log('No rooms to save');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
this.logger.log(`Saving snapshots for ${roomCount} rooms...`);
|
|
142
|
+
const savePromises = Array.from(rooms.entries()).map(async ([roomId, room]) => {
|
|
143
|
+
try {
|
|
144
|
+
await this.saveRoomSnapshot(roomId);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
const err = error;
|
|
148
|
+
this.logger.error(`Failed to save snapshot for room ${roomId}: ${err.message}`);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
await Promise.allSettled(savePromises);
|
|
152
|
+
this.logger.log(`Saved snapshots for ${roomCount} rooms`);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 保存单个房间快照
|
|
156
|
+
*/
|
|
157
|
+
async saveRoomSnapshot(roomId) {
|
|
158
|
+
const room = this.roomManager.getRoom(roomId);
|
|
159
|
+
if (!room) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const snapshot = {
|
|
163
|
+
roomId,
|
|
164
|
+
state: JSON.stringify(room),
|
|
165
|
+
timestamp: Date.now().toString(),
|
|
166
|
+
workerId: this.config.workerId,
|
|
167
|
+
};
|
|
168
|
+
await this.redis.client.hset(`gw:room:${roomId}:snapshot`, snapshot);
|
|
169
|
+
await this.redis.client.expire(`gw:room:${roomId}:snapshot`, 3600); // 1小时
|
|
170
|
+
this.logger.debug(`Saved snapshot for room ${roomId}`);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* 清理资源
|
|
174
|
+
*/
|
|
175
|
+
async cleanup() {
|
|
176
|
+
const workerId = this.config.workerId;
|
|
177
|
+
try {
|
|
178
|
+
// 关闭所有房间
|
|
179
|
+
const rooms = this.roomManager.getAllRooms();
|
|
180
|
+
for (const [roomId, room] of rooms.entries()) {
|
|
181
|
+
try {
|
|
182
|
+
// TODO: 实现closeRoom方法
|
|
183
|
+
this.logger.log(`Closing room ${roomId}`);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
const err = error;
|
|
187
|
+
this.logger.error(`Error closing room ${roomId}: ${err.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// 删除Worker注册信息
|
|
191
|
+
await this.redis.client.del(`gw:worker:${workerId}`);
|
|
192
|
+
this.logger.log('Cleanup completed');
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
const err = error;
|
|
196
|
+
this.logger.error(`Error during cleanup: ${err.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 模块销毁时的钩子
|
|
201
|
+
*/
|
|
202
|
+
async onModuleDestroy() {
|
|
203
|
+
if (!this.isShuttingDown) {
|
|
204
|
+
await this.startShutdown({ timeout: 30000, saveSnapshots: true });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 工具:Sleep
|
|
209
|
+
*/
|
|
210
|
+
sleep(ms) {
|
|
211
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
exports.GracefulShutdownService = GracefulShutdownService;
|
|
215
|
+
exports.GracefulShutdownService = GracefulShutdownService = GracefulShutdownService_1 = __decorate([
|
|
216
|
+
(0, common_1.Injectable)(),
|
|
217
|
+
__metadata("design:paramtypes", [redis_service_js_1.RedisService,
|
|
218
|
+
room_manager_service_js_1.RoomManagerService,
|
|
219
|
+
config_service_js_1.ConfigService])
|
|
220
|
+
], GracefulShutdownService);
|
|
221
|
+
//# sourceMappingURL=graceful-shutdown.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graceful-shutdown.service.js","sourceRoot":"","sources":["../../../src/lifecycle/graceful-shutdown.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lifecycle/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./graceful-shutdown.service"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lifecycle/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":""}
|
package/dist/src/main.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const dotenv_1 = require("dotenv");
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
// 加载根目录的 .env 文件(优先使用 process.cwd(),兼容开发和生产环境)
|
|
6
|
+
// 开发时从 packages/worker 运行,路径是 ../../.env
|
|
7
|
+
// 生产时从项目根目录运行,路径是 .env
|
|
8
|
+
const envPaths = [
|
|
9
|
+
(0, path_1.resolve)(process.cwd(), '.env'), // 从根目录运行
|
|
10
|
+
(0, path_1.resolve)(process.cwd(), '../../.env'), // 从 packages/worker 运行
|
|
11
|
+
(0, path_1.resolve)(__dirname, '../../../.env'), // 编译后相对路径
|
|
12
|
+
(0, path_1.resolve)(__dirname, '../../../../.env'), // 编译后备用路径
|
|
13
|
+
];
|
|
14
|
+
for (const envPath of envPaths) {
|
|
15
|
+
const result = (0, dotenv_1.config)({ path: envPath });
|
|
16
|
+
if (!result.error) {
|
|
17
|
+
console.log(`[Worker] Loaded env from: ${envPath}`);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const core_1 = require("@nestjs/core");
|
|
22
|
+
const worker_module_1 = require("./worker.module");
|
|
23
|
+
const config_service_1 = require("./config/config.service");
|
|
24
|
+
const graceful_shutdown_service_1 = require("./lifecycle/graceful-shutdown.service");
|
|
25
|
+
const room_migration_service_1 = require("./migration/room-migration.service");
|
|
26
|
+
async function bootstrap() {
|
|
27
|
+
// 创建 HTTP 应用(用于 Admin API)
|
|
28
|
+
const app = await core_1.NestFactory.create(worker_module_1.WorkerModule.forRoot());
|
|
29
|
+
const configService = app.get(config_service_1.ConfigService);
|
|
30
|
+
const shutdownService = app.get(graceful_shutdown_service_1.GracefulShutdownService);
|
|
31
|
+
const migrationService = app.get(room_migration_service_1.RoomMigrationService);
|
|
32
|
+
const adminPort = configService.adminPort;
|
|
33
|
+
// 初始化迁移服务
|
|
34
|
+
await migrationService.initialize();
|
|
35
|
+
// 启动 HTTP Admin API
|
|
36
|
+
await app.listen(adminPort);
|
|
37
|
+
console.log(`[Worker] Started, id: ${configService.workerId}`);
|
|
38
|
+
console.log(`[Worker] Admin API started on port ${adminPort}`);
|
|
39
|
+
// 优雅关闭
|
|
40
|
+
process.on('SIGINT', async () => {
|
|
41
|
+
console.log('[Worker] Received SIGINT, starting graceful shutdown...');
|
|
42
|
+
await shutdownService.startShutdown({ timeout: 60000, saveSnapshots: true });
|
|
43
|
+
await app.close();
|
|
44
|
+
process.exit(0);
|
|
45
|
+
});
|
|
46
|
+
process.on('SIGTERM', async () => {
|
|
47
|
+
console.log('[Worker] Received SIGTERM, starting graceful shutdown...');
|
|
48
|
+
await shutdownService.startShutdown({ timeout: 60000, saveSnapshots: true });
|
|
49
|
+
await app.close();
|
|
50
|
+
process.exit(0);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
bootstrap();
|
|
54
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":";;AAAA,mCAAgC;AAChC,+BAA+B;AAE/B,+CAA+C;AAC/C,yCAAyC;AACzC,uBAAuB;AACvB,MAAM,QAAQ,GAAG;IACf,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAY,SAAS;IACnD,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,EAAM,uBAAuB;IACjE,IAAA,cAAO,EAAC,SAAS,EAAE,eAAe,CAAC,EAAO,UAAU;IACpD,IAAA,cAAO,EAAC,SAAS,EAAE,kBAAkB,CAAC,EAAI,UAAU;CACrD,CAAC;AAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAA,eAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;QACpD,MAAM;IACR,CAAC;AACH,CAAC;AAED,uCAA2C;AAC3C,mDAA+C;AAC/C,4DAAwD;AACxD,qFAAgF;AAChF,+EAA0E;AAE1E,KAAK,UAAU,SAAS;IACtB,2BAA2B;IAC3B,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,4BAAY,CAAC,OAAO,EAAE,CAAC,CAAC;IAE7D,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,8BAAa,CAAC,CAAC;IAC7C,MAAM,eAAe,GAAG,GAAG,CAAC,GAAG,CAAC,mDAAuB,CAAC,CAAC;IACzD,MAAM,gBAAgB,GAAG,GAAG,CAAC,GAAG,CAAC,6CAAoB,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;IAE1C,UAAU;IACV,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IAEpC,oBAAoB;IACpB,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,yBAAyB,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,sCAAsC,SAAS,EAAE,CAAC,CAAC;IAE/D,OAAO;IACP,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QACvE,MAAM,eAAe,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACxE,MAAM,eAAe,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MetricsService } from './metrics.service';
|
|
2
|
+
/**
|
|
3
|
+
* Worker 指标端点控制器
|
|
4
|
+
* 提供 Prometheus 抓取的 /metrics 端点
|
|
5
|
+
*/
|
|
6
|
+
export declare class MetricsController {
|
|
7
|
+
private readonly metricsService;
|
|
8
|
+
constructor(metricsService: MetricsService);
|
|
9
|
+
/**
|
|
10
|
+
* GET /metrics
|
|
11
|
+
* 返回 Prometheus 格式的指标数据
|
|
12
|
+
*/
|
|
13
|
+
getMetrics(): Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=metrics.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.controller.d.ts","sourceRoot":"","sources":["../../../src/metrics/metrics.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;GAGG;AACH,qBACa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,cAAc;IAE3D;;;OAGG;IAGG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;CAGpC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MetricsController = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const metrics_service_1 = require("./metrics.service");
|
|
15
|
+
/**
|
|
16
|
+
* Worker 指标端点控制器
|
|
17
|
+
* 提供 Prometheus 抓取的 /metrics 端点
|
|
18
|
+
*/
|
|
19
|
+
let MetricsController = class MetricsController {
|
|
20
|
+
metricsService;
|
|
21
|
+
constructor(metricsService) {
|
|
22
|
+
this.metricsService = metricsService;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* GET /metrics
|
|
26
|
+
* 返回 Prometheus 格式的指标数据
|
|
27
|
+
*/
|
|
28
|
+
async getMetrics() {
|
|
29
|
+
return this.metricsService.getMetrics();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
exports.MetricsController = MetricsController;
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, common_1.Get)(),
|
|
35
|
+
(0, common_1.Header)('Cache-Control', 'no-store'),
|
|
36
|
+
__metadata("design:type", Function),
|
|
37
|
+
__metadata("design:paramtypes", []),
|
|
38
|
+
__metadata("design:returntype", Promise)
|
|
39
|
+
], MetricsController.prototype, "getMetrics", null);
|
|
40
|
+
exports.MetricsController = MetricsController = __decorate([
|
|
41
|
+
(0, common_1.Controller)('metrics'),
|
|
42
|
+
__metadata("design:paramtypes", [metrics_service_1.MetricsService])
|
|
43
|
+
], MetricsController);
|
|
44
|
+
//# sourceMappingURL=metrics.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.controller.js","sourceRoot":"","sources":["../../../src/metrics/metrics.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAyD;AACzD,uDAAmD;AAEnD;;;GAGG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACC;IAA7B,YAA6B,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;IAAG,CAAC;IAE/D;;;OAGG;IAGG,AAAN,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;IAC1C,CAAC;CACF,CAAA;AAZY,8CAAiB;AAStB;IAFL,IAAA,YAAG,GAAE;IACL,IAAA,eAAM,EAAC,eAAe,EAAE,UAAU,CAAC;;;;mDAGnC;4BAXU,iBAAiB;IAD7B,IAAA,mBAAU,EAAC,SAAS,CAAC;qCAEyB,gCAAc;GADhD,iBAAiB,CAY7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.module.d.ts","sourceRoot":"","sources":["../../../src/metrics/metrics.module.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,qBAMa,aAAa;CAAG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MetricsModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const metrics_service_1 = require("./metrics.service");
|
|
12
|
+
const metrics_controller_1 = require("./metrics.controller");
|
|
13
|
+
/**
|
|
14
|
+
* Worker 监控指标模块
|
|
15
|
+
* 全局模块,提供 Prometheus 指标收集和暴露
|
|
16
|
+
*/
|
|
17
|
+
let MetricsModule = class MetricsModule {
|
|
18
|
+
};
|
|
19
|
+
exports.MetricsModule = MetricsModule;
|
|
20
|
+
exports.MetricsModule = MetricsModule = __decorate([
|
|
21
|
+
(0, common_1.Global)(),
|
|
22
|
+
(0, common_1.Module)({
|
|
23
|
+
controllers: [metrics_controller_1.MetricsController],
|
|
24
|
+
providers: [metrics_service_1.MetricsService],
|
|
25
|
+
exports: [metrics_service_1.MetricsService],
|
|
26
|
+
})
|
|
27
|
+
], MetricsModule);
|
|
28
|
+
//# sourceMappingURL=metrics.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.module.js","sourceRoot":"","sources":["../../../src/metrics/metrics.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,uDAAmD;AACnD,6DAAyD;AAEzD;;;GAGG;AAOI,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IANzB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,sCAAiB,CAAC;QAChC,SAAS,EAAE,CAAC,gCAAc,CAAC;QAC3B,OAAO,EAAE,CAAC,gCAAc,CAAC;KAC1B,CAAC;GACW,aAAa,CAAG"}
|