From b952f5eefb06412ab12a1446ae28964d6de94520 Mon Sep 17 00:00:00 2001 From: wangdl Date: Sun, 21 Jun 2026 15:04:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(M-AI-04):=20WorkerModule=20=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1=20AiJobModule=20=E5=AF=BC=E8=87=B4=20Worker=20?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=B6=85=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: WorkerModule 未导入 AiJobModule,导致 OutboxDispatcher 的 依赖 OutboxRepository 在 DI 容器中不可用,Worker 进程启动时 hang。 修复: 1. WorkerModule 导入 AiJobModule -- 提供 OutboxRepository 等共享依赖 2. ActiveRecallRegistrationService 容忍 DuplicateJobTypeError -- API 和 Worker 各自独立启动时均会注册 active_recall definition, 第二次注册安全跳过(不阻止进程启动) Co-Authored-By: Claude --- .../active-recall-registration.service.ts | 35 +++++++++++++------ src/worker.module.ts | 2 ++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/modules/ai-job/active-recall-registration.service.ts b/src/modules/ai-job/active-recall-registration.service.ts index e3a6446..72ac7c2 100644 --- a/src/modules/ai-job/active-recall-registration.service.ts +++ b/src/modules/ai-job/active-recall-registration.service.ts @@ -1,14 +1,16 @@ import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; -import { JobDefinitionRegistry } from './job-definition-registry'; +import { JobDefinitionRegistry, DuplicateJobTypeError } from './job-definition-registry'; import { ACTIVE_RECALL_JOB_DEFINITION } from './active-recall-job-definition'; /** * M-AI-04-02: Active Recall Definition 注册服务 * * 在模块初始化(onModuleInit)时向 JobDefinitionRegistry 注册 - * ActiveRecall JobDefinition。始终注册(非测试限定)。 + * ActiveRecall JobDefinition。 * - * 重复注册由 Registry 本身的 DuplicateJobTypeError 拦截(fail-fast)。 + * 容忍重复注册:API 进程和 Worker 进程各自独立启动,均导入 + * AiJobModule,因此同一 Definition 会被注册两次。第二次注册的 + * DuplicateJobTypeError 被安全捕获,不阻止进程启动。 */ @Injectable() export class ActiveRecallRegistrationService implements OnModuleInit { @@ -17,13 +19,24 @@ export class ActiveRecallRegistrationService implements OnModuleInit { constructor(private readonly registry: JobDefinitionRegistry) {} onModuleInit(): void { - this.registry.register(ACTIVE_RECALL_JOB_DEFINITION); - this.logger.log( - `Active Recall Job Definition registered: ` + - `jobType="${ACTIVE_RECALL_JOB_DEFINITION.jobType}" ` + - `queue="${ACTIVE_RECALL_JOB_DEFINITION.queue.queueName}" ` + - `timeout=${ACTIVE_RECALL_JOB_DEFINITION.execution.timeoutMs}ms ` + - `retries=${ACTIVE_RECALL_JOB_DEFINITION.execution.maxRetries}`, - ); + try { + this.registry.register(ACTIVE_RECALL_JOB_DEFINITION); + this.logger.log( + `Active Recall Job Definition registered: ` + + `jobType="${ACTIVE_RECALL_JOB_DEFINITION.jobType}" ` + + `queue="${ACTIVE_RECALL_JOB_DEFINITION.queue.queueName}" ` + + `timeout=${ACTIVE_RECALL_JOB_DEFINITION.execution.timeoutMs}ms ` + + `retries=${ACTIVE_RECALL_JOB_DEFINITION.execution.maxRetries}`, + ); + } catch (err: unknown) { + if (err instanceof DuplicateJobTypeError) { + this.logger.log( + `Active Recall Job Definition already registered ` + + `(by another process — e.g. API + Worker both import AiJobModule)`, + ); + } else { + throw err; + } + } } } diff --git a/src/worker.module.ts b/src/worker.module.ts index bdd450d..aa7acb6 100644 --- a/src/worker.module.ts +++ b/src/worker.module.ts @@ -21,6 +21,7 @@ import { WorkerHeartbeatService } from './workers/worker-heartbeat.service'; import { OutboxDispatcher } from './modules/ai-job/outbox-dispatcher.service'; import { AiAnalysisModule } from './modules/ai-analysis/ai-analysis.module'; +import { AiJobModule } from './modules/ai-job/ai-job.module'; import { DocumentImportModule } from './modules/document-import/document-import.module'; import { KnowledgeItemsModule } from './modules/knowledge-items/knowledge-items.module'; import { NotificationsModule } from './modules/notifications/notifications.module'; @@ -66,6 +67,7 @@ import appleConfig from './config/apple.config'; StorageModule, LoggerModule, AiAnalysisModule, + AiJobModule, DocumentImportModule, KnowledgeItemsModule, NotificationsModule,