Spaces:
Starting
Starting
| /** | |
| * InngestModule β provides an Inngest client under the INNGEST token and a | |
| * WorkflowService for emitting events. The worker (Track 2b) registers the | |
| * matching functions; this module only EMITS (CLAUDE.md #2 β no direct | |
| * side-effects from the API). | |
| * | |
| * Event contract (FIXED β Track 2b consumes these exactly): | |
| * "message.received" β { missionId, conversationId, messageId } | |
| * "evidence.uploaded" β { missionId, evidenceItemId } | |
| */ | |
| import { Global, Inject, Injectable, Module } from "@nestjs/common"; | |
| import { Inngest } from "inngest"; | |
| export const INNGEST = Symbol("INNGEST"); | |
| /** WorkflowService is the only surface that sends Inngest events from the API. */ | |
| () | |
| export class WorkflowService { | |
| constructor((INNGEST) private readonly inngest: Inngest) {} | |
| async send( | |
| name: | |
| | "message.received" | |
| | "evidence.uploaded" | |
| | "mission.route_plan_requested" | |
| | "mission.facts_confirmed" | |
| | "action.execute_requested" | |
| | "action.executed" | |
| | "action.failed" | |
| | "mission.followup_due" | |
| | "email.reply_received" | |
| | "mission.reply_processed" | |
| | "mission.resolution_claimed" | |
| | "ledger.outcome_recorded" | |
| | "swarm.entity_resolution_requested" | |
| | "swarm.member_joined" | |
| | "portal.assist_requested" | |
| | "portal.assist_proceeded" | |
| | "case.lookup_requested", | |
| data: Record<string, string | boolean>, | |
| ): Promise<void> { | |
| try { | |
| await this.inngest.send({ name, data }); | |
| } catch (err) { | |
| // REVIEW_FINDINGS F1: event bus must not crash user-facing API requests. | |
| // Non-blocking: log and continue. Loop-critical events (route_plan, | |
| // execute, facts_confirmed) will be retried by the caller or surfaced | |
| // through the snapshot. A transactional outbox is the Phase-2 fix. | |
| console.error(`[WorkflowService] Failed to send event "${name}":`, err); | |
| } | |
| } | |
| } | |
| function createInngestClient(): Inngest { | |
| // In dev mode (INNGEST_DEV=1) the SDK automatically targets the local Inngest | |
| // dev server. Set INNGEST_BASE_URL to override (e.g. "http://localhost:8288"). | |
| return new Inngest({ id: "courtmitra" }); | |
| } | |
| () | |
| ({ | |
| providers: [ | |
| { | |
| provide: INNGEST, | |
| useFactory: (): Inngest => createInngestClient(), | |
| }, | |
| WorkflowService, | |
| ], | |
| exports: [INNGEST, WorkflowService], | |
| }) | |
| export class InngestModule {} | |