import type { z } from "zod"; import type { IJobQueue } from "@repo/core-shared/jobs"; import type { EventDescriptor } from "./event-descriptor"; import type { EventHandler, IEventBus } from "./event-bus.interface"; /** * Production-grade bus: for each subscriber, enqueues one Payload task per * `publish()` call. Subscribers register with their consumer-feature name so * fan-out tasks are named deterministically: `__events..`. * The actual handler invocation happens inside Payload's job runner — see the * matching task config generated by `gen event consume` (Task 39). */ export class PayloadJobsEventBus implements IEventBus { private readonly subscribers = new Map(); constructor(private readonly queue: IJobQueue) {} async publish( descriptor: EventDescriptor>, payload: T, ): Promise { descriptor.schema.parse(payload); const consumers = this.subscribers.get(descriptor.name) ?? []; await Promise.all( consumers.map((consumerFeature) => this.queue.enqueue( `__events.${descriptor.name}.${consumerFeature}`, payload, ), ), ); } subscribe( descriptor: EventDescriptor>, consumerFeature: string, _handler: EventHandler, ): void { const arr = this.subscribers.get(descriptor.name) ?? []; if (!arr.includes(consumerFeature)) arr.push(consumerFeature); this.subscribers.set(descriptor.name, arr); } }