Files
agentic-dev/packages/core-events/src/in-memory-event-bus.ts
Danijel Martinek 05f0b02856 docs(core-events): clarify subscribe consumerFeature + failFast drop
Code-quality review nits: IEventBus.subscribe docstring said "debug
tag" but InMemoryEventBus actually ignores the param entirely. Also
add a comment to InMemoryEventBus.publish noting that under failFast
only the first rejection rethrows; other failures are intentionally
dropped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 12:02:45 +02:00

43 lines
1.5 KiB
TypeScript

import type { z } from "zod";
import type { EventDescriptor } from "./event-descriptor";
import type { EventHandler, IEventBus } from "./event-bus.interface";
export type InMemoryEventBusOptions = {
/** When true, rethrow the first handler error (default: false — errors swallowed). */
failFast?: boolean;
};
export class InMemoryEventBus implements IEventBus {
private readonly handlers = new Map<string, EventHandler<unknown>[]>();
constructor(private readonly options: InMemoryEventBusOptions = {}) {}
async publish<T>(
descriptor: EventDescriptor<string, z.ZodType<T>>,
payload: T,
): Promise<void> {
descriptor.schema.parse(payload);
const subscribers = this.handlers.get(descriptor.name) ?? [];
if (subscribers.length === 0) return;
const settled = await Promise.allSettled(
subscribers.map((h) => h(payload)),
);
if (this.options.failFast) {
const failure = settled.find((s) => s.status === "rejected");
// Only the first rejection is rethrown. Other failures are intentionally
// dropped — `failFast` is a test-affordance, not a fault-tolerance design.
if (failure && failure.status === "rejected") throw failure.reason;
}
}
subscribe<T>(
descriptor: EventDescriptor<string, z.ZodType<T>>,
_consumerFeature: string,
handler: EventHandler<T>,
): void {
const arr = this.handlers.get(descriptor.name) ?? [];
arr.push(handler as EventHandler<unknown>);
this.handlers.set(descriptor.name, arr);
}
}