feat(msg): 完整实现 msg 消息服务
包含 channels/preferences/templates/grpc/kafka/outbox/push/redis 等完整实现
This commit is contained in:
@@ -6,22 +6,42 @@ import {
|
||||
} from "@nestjs/common";
|
||||
import { closeDb } from "../../config/database.js";
|
||||
import { closeEs } from "../../config/elasticsearch.js";
|
||||
import { connectKafka, disconnectKafka } from "../kafka/kafka.client.js";
|
||||
import { closeRedis } from "../redis/redis.client.js";
|
||||
import { outboxPublisher } from "../outbox/outbox.publisher.js";
|
||||
|
||||
const SERVICE_NAME = "msg";
|
||||
|
||||
/**
|
||||
* 优雅停机服务。
|
||||
* 优雅停机服务 + 资源生命周期管理。
|
||||
*
|
||||
* 信号处理由 NestJS 在 `app.listen` 之前调用 `app.enableShutdownHooks()`
|
||||
* 触发(SIGTERM / SIGINT),NestJS 会依次调用 OnApplicationShutdown 钩子。
|
||||
* 仲裁依据 G2:统一管理 DB/ES/Redis/Kafka/OutboxPublisher 生命周期。
|
||||
*
|
||||
* 关闭顺序:ES → Drizzle。先关搜索索引避免新数据丢失,再关 DB。
|
||||
* 启动顺序(onModuleInit):
|
||||
* 1. connectKafka():连接 producer + consumer(幂等,KafkaConsumerService 也会调用)
|
||||
* 2. outboxPublisher.start():启动轮询 worker,投递 pending 事件到 Kafka
|
||||
*
|
||||
* 关闭顺序(onApplicationShutdown,在 OnModuleDestroy 之后执行):
|
||||
* 1. outboxPublisher.stop():停止轮询
|
||||
* 2. disconnectKafka():断开 producer + consumer
|
||||
* 3. closeRedis():关闭 Redis 连接
|
||||
* 4. closeEs():关闭 ES 客户端
|
||||
* 5. closeDb():关闭 MySQL 连接池
|
||||
*
|
||||
* 注:KafkaConsumerService 实现 OnModuleDestroy,其 stop() 会在
|
||||
* onApplicationShutdown 之前被 NestJS 调用。disconnectKafka() 是幂等的。
|
||||
*/
|
||||
@Injectable()
|
||||
export class LifecycleService implements OnModuleInit, OnApplicationShutdown {
|
||||
private readonly logger = new Logger(LifecycleService.name);
|
||||
|
||||
onModuleInit(): void {
|
||||
async onModuleInit(): Promise<void> {
|
||||
// 1. 连接 Kafka(producer + consumer)
|
||||
await connectKafka();
|
||||
|
||||
// 2. 启动 Outbox publisher 轮询
|
||||
await outboxPublisher.start();
|
||||
|
||||
this.logger.log(`service ${SERVICE_NAME} module initialized`);
|
||||
}
|
||||
|
||||
@@ -30,15 +50,19 @@ export class LifecycleService implements OnModuleInit, OnApplicationShutdown {
|
||||
`service ${SERVICE_NAME} shutting down (signal=${signal ?? "unknown"})`,
|
||||
);
|
||||
|
||||
await this.safeDisconnect("elasticsearch", () => closeEs());
|
||||
await this.safeDisconnect("drizzle", () => closeDb());
|
||||
// 按依赖反序关闭
|
||||
await this.safeStop("outboxPublisher", () => outboxPublisher.stop());
|
||||
await this.safeStop("kafka", () => disconnectKafka());
|
||||
await this.safeStop("redis", () => closeRedis());
|
||||
await this.safeStop("elasticsearch", () => closeEs());
|
||||
await this.safeStop("drizzle", () => closeDb());
|
||||
|
||||
this.logger.log(`service ${SERVICE_NAME} shutdown complete`);
|
||||
}
|
||||
|
||||
private async safeDisconnect(
|
||||
private async safeStop(
|
||||
name: string,
|
||||
fn: () => Promise<void>,
|
||||
fn: () => Promise<unknown>,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await fn();
|
||||
|
||||
Reference in New Issue
Block a user