M8: Debezium CDC now handles outbox table to Kafka (ADR-032) - Remove OutboxPublisher class from shared-ts - Remove publisher from iam/core-edu/content/msg lifecycle and modules - OutboxService retained for transactional outbox table writes - Debezium monitors binlog and pushes to Kafka automatically
88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
import {
|
||
Module,
|
||
NestModule,
|
||
MiddlewareConsumer,
|
||
OnModuleInit,
|
||
Logger,
|
||
} from "@nestjs/common";
|
||
import { APP_GUARD } from "@nestjs/core";
|
||
import { IamModule } from "./iam/iam.module.js";
|
||
import { HealthModule } from "./shared/health/health.module.js";
|
||
import { PermissionGuard } from "./middleware/permission.guard.js";
|
||
import { AuthMiddleware } from "./middleware/auth.middleware.js";
|
||
import { LifecycleService } from "./shared/lifecycle/lifecycle.service.js";
|
||
import { GraphqlModule } from "./graphql/graphql.module.js";
|
||
import { RouterAuthGuard } from "./graphql/router-auth.guard.js";
|
||
import { OutboxModule } from "@edu/shared-ts/outbox";
|
||
import { getDbInstance } from "./config/database.js";
|
||
import { connectKafkaProducer, IAM_KAFKA_TOPICS } from "./config/kafka.js";
|
||
|
||
/**
|
||
* IAM 根模块(v2.1)。
|
||
*
|
||
* 装配:
|
||
* - IamModule(业务)
|
||
* - HealthModule(健康检查)
|
||
* - GraphqlModule(Apollo Federation 子图,v2.1 新增)
|
||
* - OutboxModule(事务性事件发布,I5 裁决;v2.1 后投递由 Debezium 完成)
|
||
* - AuthMiddleware(从 Gateway 注入的 x-user-* 头部解析用户身份)
|
||
* - PermissionGuard(APP_GUARD,DB 驱动 + Redis 缓存,I3 裁决)
|
||
* - RouterAuthGuard(APP_GUARD,仅 /graphql 端点生效,ADR-036)
|
||
*/
|
||
@Module({
|
||
imports: [
|
||
IamModule,
|
||
HealthModule,
|
||
GraphqlModule,
|
||
OutboxModule.forRoot({
|
||
config: {
|
||
tableName: "iam_outbox",
|
||
kafkaTopic: IAM_KAFKA_TOPICS.USER_EVENTS,
|
||
maxRetryCount: 5,
|
||
},
|
||
db: getDbInstance(),
|
||
}),
|
||
],
|
||
providers: [
|
||
{ provide: APP_GUARD, useClass: PermissionGuard },
|
||
{ provide: APP_GUARD, useClass: RouterAuthGuard },
|
||
LifecycleService,
|
||
],
|
||
})
|
||
export class AppModule implements NestModule, OnModuleInit {
|
||
private readonly logger = new Logger(AppModule.name);
|
||
|
||
async onModuleInit(): Promise<void> {
|
||
// 连接 Kafka producer(健康检查 /healthz 依赖 producer 探活)
|
||
// v2.1(M8):OutboxPublisher 轮询线程已移除,outbox 投递由 Debezium CDC 接管
|
||
try {
|
||
await connectKafkaProducer();
|
||
this.logger.log("Kafka producer connected");
|
||
} catch (error) {
|
||
this.logger.error(
|
||
`Kafka producer connect failed: ${error instanceof Error ? error.message : String(error)}`,
|
||
);
|
||
}
|
||
}
|
||
|
||
configure(consumer: MiddlewareConsumer): void {
|
||
// AuthMiddleware 应用于需要鉴权的 /v1/iam 路由
|
||
// 公开端点(register/login/refresh/jwks/health/metrics)不走此中间件
|
||
consumer
|
||
.apply(AuthMiddleware)
|
||
.forRoutes(
|
||
"v1/iam/me",
|
||
"v1/iam/logout",
|
||
"v1/iam/change-password",
|
||
"v1/iam/viewports",
|
||
"v1/iam/permissions/effective",
|
||
"v1/iam/children",
|
||
"v1/iam/roles",
|
||
"v1/iam/permissions",
|
||
"v1/iam/users",
|
||
"v1/iam/audit",
|
||
"v1/iam/totp",
|
||
);
|
||
}
|
||
}
|