Files
Edu/services/msg/src/main.ts
SpecialX 7b7abbb309 feat(msg): 完整实现 msg 消息服务
包含 channels/preferences/templates/grpc/kafka/outbox/push/redis 等完整实现
2026-07-10 19:09:52 +08:00

78 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module.js";
import { GlobalErrorFilter } from "./shared/errors/global-error.filter.js";
import { initTracer, shutdownTracer } from "./shared/observability/tracer.js";
import { env } from "./config/env.js";
import { logger } from "./shared/observability/logger.js";
import { checkEsConnection } from "./config/elasticsearch.js";
import { grpcMicroserviceOptions } from "./config/grpc.js";
import { metricsRegistry } from "./shared/observability/metrics.js";
import type { Request, Response } from "express";
/**
* msg 服务启动入口。
*
* 仲裁依据:
* - M1gRPC 50056 启用connectMicroservice
* - HTTP REST 3007 + gRPC 50056 双协议入口
* - enableShutdownHooks()NestJS 自动处理 SIGTERM/SIGINT → onApplicationShutdown
*
* 启动流程:
* 1. initTracers()OpenTelemetry 链路追踪
* 2. checkEsConnection()ES 探活(降级安全,不阻断启动)
* 3. NestFactory.create(AppModule):创建 app触发 onModuleInit
* - LifecycleService.onModuleInitconnectKafka + outboxPublisher.start
* - KafkaConsumerService.onModuleInitconnectKafka + consumer.run
* 4. connectMicroservice(grpcMicroserviceOptions):注册 gRPC 服务
* 5. startAllMicroservices():启动 gRPC 50056
* 6. listen(PORT):启动 HTTP REST 3007
*/
async function bootstrap(): Promise<void> {
initTracer();
// ES 探活:未配置或失败时进入降级模式,不阻断启动。
await checkEsConnection();
const app = await NestFactory.create(AppModule, {
logger: ["log", "error", "warn"],
});
app.useGlobalFilters(new GlobalErrorFilter());
app.enableShutdownHooks();
// 注册 gRPC 微服务50056
app.connectMicroservice(grpcMicroserviceOptions);
// Prometheus 指标端点:不鉴权,供 Prometheus 抓取。
app.getHttpAdapter().get("/metrics", async (_req: Request, res: Response) => {
res.set("Content-Type", metricsRegistry.contentType);
res.end(await metricsRegistry.metrics());
});
// 启动 gRPC 微服务 + HTTP 服务
await app.startAllMicroservices();
await app.listen(env.PORT);
logger.info(
{ httpPort: env.PORT, grpcPort: env.GRPC_PORT },
"Msg service started (HTTP + gRPC)",
);
// 兜底信号处理enableShutdownHooks 已处理 SIGTERM/SIGINT
// 此处仅确保进程退出(防止悬挂连接阻塞退出)。
const shutdown = async (signal: string): Promise<void> => {
logger.info({ signal }, "Shutting down gracefully...");
await app.close();
await shutdownTracer();
process.exit(0);
};
process.on("SIGTERM", () => void shutdown("SIGTERM"));
process.on("SIGINT", () => void shutdown("SIGINT"));
}
void bootstrap().catch((err: unknown) => {
logger.error({ err }, "Failed to start msg service");
process.exit(1);
});