bubus 1.7.3 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +775 -266
  2. package/dist/esm/async_context.js +39 -0
  3. package/dist/esm/async_context.js.map +7 -0
  4. package/dist/esm/base_event.js +825 -0
  5. package/dist/esm/base_event.js.map +7 -0
  6. package/dist/esm/bridge_jsonl.js +150 -0
  7. package/dist/esm/bridge_jsonl.js.map +7 -0
  8. package/dist/esm/bridge_nats.js +88 -0
  9. package/dist/esm/bridge_nats.js.map +7 -0
  10. package/dist/esm/bridge_postgres.js +231 -0
  11. package/dist/esm/bridge_postgres.js.map +7 -0
  12. package/dist/esm/bridge_redis.js +155 -0
  13. package/dist/esm/bridge_redis.js.map +7 -0
  14. package/dist/esm/bridge_sqlite.js +235 -0
  15. package/dist/esm/bridge_sqlite.js.map +7 -0
  16. package/dist/esm/bridges.js +306 -0
  17. package/dist/esm/bridges.js.map +7 -0
  18. package/dist/esm/event_bus.js +1046 -0
  19. package/dist/esm/event_bus.js.map +7 -0
  20. package/dist/esm/event_handler.js +279 -0
  21. package/dist/esm/event_handler.js.map +7 -0
  22. package/dist/esm/event_history.js +172 -0
  23. package/dist/esm/event_history.js.map +7 -0
  24. package/dist/esm/event_result.js +426 -0
  25. package/dist/esm/event_result.js.map +7 -0
  26. package/dist/esm/events_suck.js +39 -0
  27. package/dist/esm/events_suck.js.map +7 -0
  28. package/dist/esm/helpers.js +64 -0
  29. package/dist/esm/helpers.js.map +7 -0
  30. package/dist/esm/index.js +37 -16206
  31. package/dist/esm/index.js.map +4 -4
  32. package/dist/esm/lock_manager.js +323 -0
  33. package/dist/esm/lock_manager.js.map +7 -0
  34. package/dist/esm/logging.js +196 -0
  35. package/dist/esm/logging.js.map +7 -0
  36. package/dist/esm/middlewares.js +1 -0
  37. package/dist/esm/middlewares.js.map +7 -0
  38. package/dist/esm/optional_deps.js +34 -0
  39. package/dist/esm/optional_deps.js.map +7 -0
  40. package/dist/esm/retry.js +237 -0
  41. package/dist/esm/retry.js.map +7 -0
  42. package/dist/esm/timing.js +56 -0
  43. package/dist/esm/timing.js.map +7 -0
  44. package/dist/esm/types.js +84 -0
  45. package/dist/esm/types.js.map +7 -0
  46. package/dist/types/async_context.d.ts +4 -2
  47. package/dist/types/base_event.d.ts +124 -76
  48. package/dist/types/bridge_jsonl.d.ts +26 -0
  49. package/dist/types/bridge_nats.d.ts +20 -0
  50. package/dist/types/bridge_postgres.d.ts +31 -0
  51. package/dist/types/bridge_redis.d.ts +34 -0
  52. package/dist/types/bridge_sqlite.d.ts +30 -0
  53. package/dist/types/bridges.d.ts +49 -0
  54. package/dist/types/event_bus.d.ts +99 -68
  55. package/dist/types/event_handler.d.ts +73 -19
  56. package/dist/types/event_history.d.ts +45 -0
  57. package/dist/types/event_result.d.ts +60 -38
  58. package/dist/types/events_suck.d.ts +40 -0
  59. package/dist/types/helpers.d.ts +1 -0
  60. package/dist/types/index.d.ts +13 -2
  61. package/dist/types/lock_manager.d.ts +33 -31
  62. package/dist/types/logging.d.ts +5 -1
  63. package/dist/types/middlewares.d.ts +13 -0
  64. package/dist/types/optional_deps.d.ts +3 -0
  65. package/dist/types/retry.d.ts +52 -0
  66. package/dist/types/timing.d.ts +3 -0
  67. package/dist/types/types.d.ts +18 -7
  68. package/package.json +32 -11
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/event_bus.ts"],
4
+ "sourcesContent": ["import { BaseEvent, type BaseEventJSON } from './base_event.js'\nimport { EventHistory } from './event_history.js'\nimport { EventResult } from './event_result.js'\nimport { captureAsyncContext } from './async_context.js'\nimport { _runWithSlowMonitor, _runWithTimeout } from './timing.js'\nimport {\n AsyncLock,\n type EventConcurrencyMode,\n type EventHandlerConcurrencyMode,\n type EventHandlerCompletionMode,\n LockManager,\n} from './lock_manager.js'\nimport {\n EventHandler,\n EventHandlerAbortedError,\n EventHandlerCancelledError,\n EventHandlerTimeoutError,\n type EphemeralFindEventHandler,\n type EventHandlerJSON,\n} from './event_handler.js'\nimport type { EventBusMiddleware, EventBusMiddlewareCtor, EventBusMiddlewareInput } from './middlewares.js'\nimport { logTree } from './logging.js'\nimport { v7 as uuidv7 } from 'uuid'\nimport { monotonicDatetime } from './helpers.js'\n\nimport { normalizeEventPattern } from './types.js'\nimport type { EventClass, EventHandlerCallable, EventPattern, FindOptions, UntypedEventHandlerFunction } from './types.js'\n\nexport type EventBusOptions = {\n id?: string\n max_history_size?: number | null\n max_history_drop?: boolean\n\n // per-event options\n event_concurrency?: EventConcurrencyMode | null\n event_timeout?: number | null // default handler timeout in seconds, applied when event.event_timeout is undefined\n event_slow_timeout?: number | null // threshold before a warning is logged about slow event processing\n\n // per-event-handler options\n event_handler_concurrency?: EventHandlerConcurrencyMode | null\n event_handler_completion?: EventHandlerCompletionMode\n event_handler_slow_timeout?: number | null // threshold before a warning is logged about slow handler execution\n event_handler_detect_file_paths?: boolean // autodetect source code file and lineno where handlers are defined for better logs (slightly slower because Error().stack introspection to fine files is expensive)\n middlewares?: EventBusMiddlewareInput[]\n}\n\nexport type EventBusJSON = {\n id: string\n name: string\n max_history_size: number | null\n max_history_drop: boolean\n event_concurrency: EventConcurrencyMode\n event_timeout: number | null\n event_slow_timeout: number | null\n event_handler_concurrency: EventHandlerConcurrencyMode\n event_handler_completion: EventHandlerCompletionMode\n event_handler_slow_timeout: number | null\n event_handler_detect_file_paths: boolean\n handlers: Record<string, EventHandlerJSON>\n handlers_by_key: Record<string, string[]>\n event_history: Record<string, BaseEventJSON>\n pending_event_queue: string[]\n}\n\n// Global registry of all EventBus instances to allow for cross-bus coordination\n// when global-serial concurrency mode is used.\nexport class GlobalEventBusRegistry {\n private _bus_refs = new Set<WeakRef<EventBus>>()\n\n add(bus: EventBus): void {\n this._bus_refs.add(new WeakRef(bus))\n }\n\n discard(bus: EventBus): void {\n for (const ref of this._bus_refs) {\n const current = ref.deref()\n if (!current || current === bus) {\n this._bus_refs.delete(ref)\n }\n }\n }\n\n has(bus: EventBus): boolean {\n for (const ref of this._bus_refs) {\n const current = ref.deref()\n if (!current) {\n this._bus_refs.delete(ref)\n continue\n }\n if (current === bus) {\n return true\n }\n }\n return false\n }\n\n get size(): number {\n let count = 0\n for (const ref of this._bus_refs) {\n if (ref.deref()) {\n count += 1\n } else {\n this._bus_refs.delete(ref)\n }\n }\n return count\n }\n\n *[Symbol.iterator](): IterableIterator<EventBus> {\n for (const ref of this._bus_refs) {\n const bus = ref.deref()\n if (bus) {\n yield bus\n } else {\n this._bus_refs.delete(ref)\n }\n }\n }\n\n findBusById(bus_id: string): EventBus | undefined {\n for (const bus of this) {\n if (bus.id === bus_id) {\n return bus\n }\n }\n return undefined\n }\n\n findEventById(event_id: string): BaseEvent | null {\n for (const bus of this) {\n const event = bus.event_history.getEvent(event_id)\n if (event) {\n return event\n }\n }\n return null\n }\n}\n\nexport class EventBus {\n private static _registry_by_constructor = new WeakMap<Function, GlobalEventBusRegistry>()\n private static _global_event_lock_by_constructor = new WeakMap<Function, AsyncLock>()\n\n private static getRegistryForConstructor(constructor_fn: Function): GlobalEventBusRegistry {\n const existing_registry = EventBus._registry_by_constructor.get(constructor_fn)\n if (existing_registry) {\n return existing_registry\n }\n const created_registry = new GlobalEventBusRegistry()\n EventBus._registry_by_constructor.set(constructor_fn, created_registry)\n return created_registry\n }\n\n private static getGlobalEventLockForConstructor(constructor_fn: Function): AsyncLock {\n const existing_lock = EventBus._global_event_lock_by_constructor.get(constructor_fn)\n if (existing_lock) {\n return existing_lock\n }\n const created_lock = new AsyncLock(1)\n EventBus._global_event_lock_by_constructor.set(constructor_fn, created_lock)\n return created_lock\n }\n\n static get all_instances(): GlobalEventBusRegistry {\n return EventBus.getRegistryForConstructor(this)\n }\n\n get all_instances(): GlobalEventBusRegistry {\n return EventBus.getRegistryForConstructor(this.constructor as Function)\n }\n\n get _lock_for_event_global_serial(): AsyncLock {\n return EventBus.getGlobalEventLockForConstructor(this.constructor as Function)\n }\n\n id: string // unique uuidv7 identifier for the event bus\n name: string // name of the event bus, recommended to include the word \"Bus\" in the name for clarity in logs\n\n // configuration options\n event_timeout: number | null\n event_concurrency: EventConcurrencyMode\n event_handler_concurrency: EventHandlerConcurrencyMode\n event_handler_completion: EventHandlerCompletionMode\n event_handler_detect_file_paths: boolean\n\n // slow processing warning timeout settings\n event_handler_slow_timeout: number | null\n event_slow_timeout: number | null\n\n // public runtime state\n handlers: Map<string, EventHandler> // map of handler uuidv5 ids to EventHandler objects\n handlers_by_key: Map<string, string[]> // map of normalized event_pattern to ordered handler ids\n event_history: EventHistory<BaseEvent> // map of event uuidv7 ids to processed BaseEvent objects\n\n // internal runtime state\n pending_event_queue: BaseEvent[] // queue of events that have been emitted to the bus but not yet processed\n in_flight_event_ids: Set<string> // set of event ids that are currently being processed by the bus\n runloop_running: boolean\n locks: LockManager\n find_waiters: Set<EphemeralFindEventHandler> // set of EphemeralFindEventHandler objects that are waiting for a matching future event\n middlewares: EventBusMiddleware[]\n\n private static normalizeMiddlewares(middlewares?: EventBusMiddlewareInput[]): EventBusMiddleware[] {\n const normalized: EventBusMiddleware[] = []\n for (const middleware of middlewares ?? []) {\n if (!middleware) {\n continue\n }\n if (typeof middleware === 'function') {\n normalized.push(new (middleware as EventBusMiddlewareCtor)())\n } else {\n normalized.push(middleware as EventBusMiddleware)\n }\n }\n return normalized\n }\n\n constructor(name: string = 'EventBus', options: EventBusOptions = {}) {\n this.id = options.id ?? uuidv7()\n this.name = name\n\n // set configuration options\n this.event_concurrency = options.event_concurrency ?? 'bus-serial'\n this.event_handler_concurrency = options.event_handler_concurrency ?? 'serial'\n this.event_handler_completion = options.event_handler_completion ?? 'all'\n this.event_handler_detect_file_paths = options.event_handler_detect_file_paths ?? true\n this.event_timeout = options.event_timeout === undefined ? 60 : options.event_timeout\n this.event_handler_slow_timeout = options.event_handler_slow_timeout === undefined ? 30 : options.event_handler_slow_timeout\n this.event_slow_timeout = options.event_slow_timeout === undefined ? 300 : options.event_slow_timeout\n\n // initialize runtime state\n this.runloop_running = false\n this.handlers = new Map()\n this.handlers_by_key = new Map()\n this.find_waiters = new Set()\n this.event_history = new EventHistory({\n max_history_size: options.max_history_size === undefined ? 100 : options.max_history_size,\n max_history_drop: options.max_history_drop ?? false,\n })\n this.pending_event_queue = []\n this.in_flight_event_ids = new Set()\n this.locks = new LockManager(this)\n this.middlewares = EventBus.normalizeMiddlewares(options.middlewares)\n\n this.all_instances.add(this)\n\n this.dispatch = this.dispatch.bind(this)\n this.emit = this.emit.bind(this)\n }\n\n toString(): string {\n return `${this.name}#${this.id.slice(-4)}`\n }\n\n scheduleMicrotask(fn: () => void): void {\n if (typeof queueMicrotask === 'function') {\n queueMicrotask(fn)\n return\n }\n void Promise.resolve().then(fn)\n }\n\n private async _runMiddlewareHook(hook: keyof EventBusMiddleware, args: unknown[]): Promise<void> {\n if (this.middlewares.length === 0) {\n return\n }\n for (const middleware of this.middlewares) {\n const callback = middleware[hook]\n if (!callback) {\n continue\n }\n await (callback as (...hook_args: unknown[]) => void | Promise<void>).apply(middleware, args)\n }\n }\n\n async onEventChange(event: BaseEvent, status: 'pending' | 'started' | 'completed'): Promise<void> {\n await this._onEventChange(event, status)\n }\n\n async onEventResultChange(event: BaseEvent, result: EventResult, status: 'pending' | 'started' | 'completed'): Promise<void> {\n await this._onEventResultChange(event, result, status)\n }\n\n private async _onEventChange(event: BaseEvent, status: 'pending' | 'started' | 'completed'): Promise<void> {\n await this._runMiddlewareHook('onEventChange', [this, event, status])\n }\n\n private async _onEventResultChange(event: BaseEvent, result: EventResult, status: 'pending' | 'started' | 'completed'): Promise<void> {\n await this._runMiddlewareHook('onEventResultChange', [this, event, result, status])\n }\n\n private async _onBusHandlersChange(handler: EventHandler, registered: boolean): Promise<void> {\n await this._runMiddlewareHook('onBusHandlersChange', [this, handler, registered])\n }\n\n private _finalizeEventTimeout(\n event: BaseEvent,\n pending_entries: Array<{\n handler: EventHandler\n result: EventResult\n }>,\n timeout_error: EventHandlerTimeoutError\n ): void {\n const timeout_seconds = timeout_error.timeout_seconds ?? event.event_timeout ?? null\n event._cancelPendingChildProcessing(timeout_error)\n\n for (const entry of pending_entries) {\n const result = entry.result\n if (result.status === 'completed') {\n continue\n }\n if (result.status === 'error') {\n continue\n }\n if (result.status === 'started') {\n result._lock?.exitHandlerRun()\n result._releaseQueueJumpPauses()\n const aborted_error = new EventHandlerAbortedError(`Aborted running handler due to event timeout`, {\n event_result: result,\n timeout_seconds,\n cause: timeout_error,\n })\n result._markError(aborted_error)\n result._signalAbort(aborted_error)\n continue\n }\n const cancelled_error = new EventHandlerCancelledError(`Cancelled pending handler due to event timeout`, {\n event_result: result,\n timeout_seconds,\n cause: timeout_error,\n })\n result._markError(cancelled_error)\n }\n\n event.event_pending_bus_count = Math.max(0, event.event_pending_bus_count - 1)\n event._markCompleted()\n }\n\n private _createEventTimeoutError(\n event: BaseEvent,\n pending_entries: Array<{\n handler: EventHandler\n result: EventResult\n }>,\n timeout_seconds: number\n ): EventHandlerTimeoutError {\n const timeout_anchor =\n pending_entries.find((entry) => entry.result.status === 'started') ??\n pending_entries.find((entry) => entry.result.status === 'pending') ??\n pending_entries[0]!\n return new EventHandlerTimeoutError(\n `${this.toString()}.on(${event.toString()}, ${timeout_anchor.result.handler.toString()}) timed out after ${timeout_seconds}s`,\n {\n event_result: timeout_anchor.result,\n timeout_seconds,\n }\n )\n }\n\n private async _runHandlersWithTimeout(\n event: BaseEvent,\n pending_entries: Array<{\n handler: EventHandler\n result: EventResult\n }>,\n event_timeout: number | null,\n fn: () => Promise<void>\n ): Promise<void> {\n try {\n if (event_timeout === null || pending_entries.length === 0) {\n await fn()\n } else {\n await _runWithTimeout(event_timeout, () => this._createEventTimeoutError(event, pending_entries, event_timeout), fn)\n }\n } catch (error) {\n if (error instanceof EventHandlerTimeoutError) {\n this._finalizeEventTimeout(event, pending_entries, error)\n return\n }\n throw error\n }\n }\n\n private _markEventCompletedIfNeeded(event: BaseEvent): void {\n if (event.event_status !== 'completed') {\n event.event_pending_bus_count = Math.max(0, event.event_pending_bus_count - 1)\n event._markCompleted(false)\n }\n if (\n this.event_history.max_history_size !== null &&\n this.event_history.max_history_size > 0 &&\n this.event_history.size > this.event_history.max_history_size\n ) {\n this.event_history.trimEventHistory({\n is_event_complete: (candidate_event) => candidate_event.event_status === 'completed',\n on_remove: (candidate_event) => candidate_event._gc(),\n owner_label: this.toString(),\n max_history_size: this.event_history.max_history_size,\n max_history_drop: this.event_history.max_history_drop,\n })\n }\n }\n\n toJSON(): EventBusJSON {\n const handlers: Record<string, EventHandlerJSON> = {}\n for (const [handler_id, handler] of this.handlers.entries()) {\n handlers[handler_id] = handler.toJSON()\n }\n\n const handlers_by_key: Record<string, string[]> = {}\n for (const [key, ids] of this.handlers_by_key.entries()) {\n handlers_by_key[key] = [...ids]\n }\n\n const event_history: Record<string, BaseEventJSON> = {}\n for (const [event_id, event] of this.event_history.entries()) {\n event_history[event_id] = event.toJSON()\n }\n\n const pending_event_queue: string[] = []\n for (const event of this.pending_event_queue) {\n const event_id = event.event_id\n if (!event_history[event_id]) {\n event_history[event_id] = event.toJSON()\n }\n pending_event_queue.push(event_id)\n }\n\n return {\n id: this.id,\n name: this.name,\n max_history_size: this.event_history.max_history_size,\n max_history_drop: this.event_history.max_history_drop,\n event_concurrency: this.event_concurrency,\n event_timeout: this.event_timeout,\n event_slow_timeout: this.event_slow_timeout,\n event_handler_concurrency: this.event_handler_concurrency,\n event_handler_completion: this.event_handler_completion,\n event_handler_slow_timeout: this.event_handler_slow_timeout,\n event_handler_detect_file_paths: this.event_handler_detect_file_paths,\n handlers,\n handlers_by_key,\n event_history,\n pending_event_queue,\n }\n }\n\n private static _stubHandlerFn(): EventHandlerCallable {\n return (() => undefined) as EventHandlerCallable\n }\n\n private static _upsertHandlerIndex(bus: EventBus, event_pattern: string, handler_id: string): void {\n const ids = bus.handlers_by_key.get(event_pattern)\n if (ids) {\n if (!ids.includes(handler_id)) {\n ids.push(handler_id)\n }\n return\n }\n bus.handlers_by_key.set(event_pattern, [handler_id])\n }\n\n private static _linkEventResultHandlers(event: BaseEvent, bus: EventBus): void {\n for (const [map_key, result] of Array.from(event.event_results.entries())) {\n const handler_id = result.handler_id\n const existing_handler = bus.handlers.get(handler_id)\n if (existing_handler) {\n result.handler = existing_handler\n } else {\n const source = result.handler\n const handler_entry = EventHandler.fromJSON(\n {\n ...source.toJSON(),\n id: handler_id,\n event_pattern: source.event_pattern || event.event_type,\n eventbus_name: source.eventbus_name || bus.name,\n eventbus_id: source.eventbus_id || bus.id,\n },\n EventBus._stubHandlerFn()\n )\n bus.handlers.set(handler_entry.id, handler_entry)\n EventBus._upsertHandlerIndex(bus, handler_entry.event_pattern, handler_entry.id)\n result.handler = handler_entry\n }\n\n if (map_key !== handler_id) {\n event.event_results.delete(map_key)\n event.event_results.set(handler_id, result)\n }\n }\n }\n\n static fromJSON(data: unknown): EventBus {\n if (!data || typeof data !== 'object') {\n throw new Error('EventBus.fromJSON(data) requires an object')\n }\n const record = data as Record<string, unknown>\n const name = typeof record.name === 'string' ? record.name : 'EventBus'\n const options: EventBusOptions = {}\n\n if (typeof record.id === 'string') options.id = record.id\n if (typeof record.max_history_size === 'number' || record.max_history_size === null) options.max_history_size = record.max_history_size\n if (typeof record.max_history_drop === 'boolean') options.max_history_drop = record.max_history_drop\n if (\n record.event_concurrency === 'global-serial' ||\n record.event_concurrency === 'bus-serial' ||\n record.event_concurrency === 'parallel'\n ) {\n options.event_concurrency = record.event_concurrency\n }\n if (typeof record.event_timeout === 'number' || record.event_timeout === null) options.event_timeout = record.event_timeout\n if (typeof record.event_slow_timeout === 'number' || record.event_slow_timeout === null)\n options.event_slow_timeout = record.event_slow_timeout\n if (record.event_handler_concurrency === 'serial' || record.event_handler_concurrency === 'parallel') {\n options.event_handler_concurrency = record.event_handler_concurrency\n }\n if (record.event_handler_completion === 'all' || record.event_handler_completion === 'first') {\n options.event_handler_completion = record.event_handler_completion\n }\n if (typeof record.event_handler_slow_timeout === 'number' || record.event_handler_slow_timeout === null) {\n options.event_handler_slow_timeout = record.event_handler_slow_timeout\n }\n if (typeof record.event_handler_detect_file_paths === 'boolean') {\n options.event_handler_detect_file_paths = record.event_handler_detect_file_paths\n }\n const bus = new EventBus(name, options)\n\n if (!record.handlers || typeof record.handlers !== 'object' || Array.isArray(record.handlers)) {\n throw new Error('EventBus.fromJSON(data) requires handlers as an id-keyed object')\n }\n for (const [handler_id, payload] of Object.entries(record.handlers as Record<string, unknown>)) {\n if (!payload || typeof payload !== 'object') {\n continue\n }\n const parsed = EventHandler.fromJSON(\n {\n ...(payload as Record<string, unknown>),\n id: typeof (payload as { id?: unknown }).id === 'string' ? (payload as { id: string }).id : handler_id,\n },\n EventBus._stubHandlerFn()\n )\n bus.handlers.set(parsed.id, parsed)\n }\n\n if (!record.handlers_by_key || typeof record.handlers_by_key !== 'object' || Array.isArray(record.handlers_by_key)) {\n throw new Error('EventBus.fromJSON(data) requires handlers_by_key as an object')\n }\n bus.handlers_by_key.clear()\n for (const [raw_key, raw_ids] of Object.entries(record.handlers_by_key as Record<string, unknown>)) {\n if (!Array.isArray(raw_ids)) {\n continue\n }\n const ids = raw_ids.filter((id): id is string => typeof id === 'string')\n bus.handlers_by_key.set(raw_key, ids)\n }\n\n if (!record.event_history || typeof record.event_history !== 'object' || Array.isArray(record.event_history)) {\n throw new Error('EventBus.fromJSON(data) requires event_history as an id-keyed object')\n }\n for (const [event_id, payload] of Object.entries(record.event_history as Record<string, unknown>)) {\n if (!payload || typeof payload !== 'object') {\n continue\n }\n const event = BaseEvent.fromJSON({\n ...(payload as Record<string, unknown>),\n event_id: typeof (payload as { event_id?: unknown }).event_id === 'string' ? (payload as { event_id: string }).event_id : event_id,\n })\n event.bus = bus\n bus.event_history.set(event.event_id, event)\n }\n\n if (!Array.isArray(record.pending_event_queue)) {\n throw new Error('EventBus.fromJSON(data) requires pending_event_queue as an array of event ids')\n }\n const raw_pending_event_queue = record.pending_event_queue\n const pending_event_ids: string[] = []\n for (const item of raw_pending_event_queue) {\n if (typeof item === 'string') {\n pending_event_ids.push(item)\n }\n }\n bus.pending_event_queue = pending_event_ids\n .map((event_id) => bus.event_history.get(event_id))\n .filter((event): event is BaseEvent => Boolean(event))\n\n for (const event of bus.event_history.values()) {\n EventBus._linkEventResultHandlers(event, bus)\n }\n\n // Reset runtime execution state after restore. Queue/history/handlers are restored,\n // but lock internals should always restart from a clean default state.\n bus.in_flight_event_ids.clear()\n bus.runloop_running = false\n bus.locks.clear()\n bus.find_waiters.clear()\n\n return bus\n }\n\n get label(): string {\n return `${this.name}#${this.id.slice(-4)}`\n }\n\n removeEventFromPendingQueue(event: BaseEvent): number {\n const original_event = event._event_original ?? event\n let removed_count = 0\n for (let index = this.pending_event_queue.length - 1; index >= 0; index -= 1) {\n const queued_event = this.pending_event_queue[index]\n const queued_original = queued_event._event_original ?? queued_event\n if (queued_original.event_id !== original_event.event_id) {\n continue\n }\n this.pending_event_queue.splice(index, 1)\n removed_count += 1\n }\n return removed_count\n }\n\n isEventInFlightOrQueued(event_id: string): boolean {\n if (this.in_flight_event_ids.has(event_id)) {\n return true\n }\n for (const queued_event of this.pending_event_queue) {\n const queued_original = queued_event._event_original ?? queued_event\n if (queued_original.event_id === event_id) {\n return true\n }\n }\n return false\n }\n\n removeEventFromHistory(event_id: string): boolean {\n return this.event_history.delete(event_id)\n }\n\n // destroy the event bus and all its state to allow for garbage collection\n destroy(): void {\n this.all_instances.discard(this)\n this.handlers.clear()\n this.handlers_by_key.clear()\n for (const event of this.event_history.values()) {\n event._gc()\n }\n this.event_history.clear()\n this.pending_event_queue.length = 0\n this.in_flight_event_ids.clear()\n this.find_waiters.clear()\n this.locks.clear()\n }\n\n on<T extends BaseEvent>(event_pattern: EventClass<T>, handler: EventHandlerCallable<T>, options?: Partial<EventHandler>): EventHandler\n on<T extends BaseEvent>(\n event_pattern: string | '*',\n handler: UntypedEventHandlerFunction<T>,\n options?: Partial<EventHandler>\n ): EventHandler\n on(\n event_pattern: EventPattern | '*',\n handler: EventHandlerCallable | UntypedEventHandlerFunction,\n options: Partial<EventHandler> = {}\n ): EventHandler {\n const normalized_key = normalizeEventPattern(event_pattern) // get string event_type or '*'\n const handler_name = handler.name || 'anonymous' // get handler function name or 'anonymous' if the handler is an anonymous/arrow function\n const handler_entry = new EventHandler({\n handler: handler as EventHandlerCallable,\n handler_name,\n handler_registered_at: monotonicDatetime(),\n event_pattern: normalized_key,\n eventbus_name: this.name,\n eventbus_id: this.id,\n ...options,\n })\n if (this.event_handler_detect_file_paths) {\n // optionally perform (expensive) file path detection for the handler using Error().stack introspection\n // makes logs much more useful for debugging, but is expensive to do if not needed\n handler_entry._detectHandlerFilePath()\n }\n\n this.handlers.set(handler_entry.id, handler_entry)\n const ids = this.handlers_by_key.get(handler_entry.event_pattern)\n if (ids) ids.push(handler_entry.id)\n else this.handlers_by_key.set(handler_entry.event_pattern, [handler_entry.id])\n this.scheduleMicrotask(() => {\n void this._onBusHandlersChange(handler_entry, true)\n })\n return handler_entry\n }\n\n off<T extends BaseEvent>(event_pattern: EventPattern<T> | '*', handler?: EventHandlerCallable<T> | string | EventHandler): void {\n const normalized_key = normalizeEventPattern(event_pattern)\n if (typeof handler === 'object' && handler instanceof EventHandler && handler.id !== undefined) {\n handler = handler.id\n }\n const match_by_id = typeof handler === 'string'\n for (const entry of this.handlers.values()) {\n if (entry.event_pattern !== normalized_key) {\n continue\n }\n const handler_id = entry.id\n if (handler === undefined || (match_by_id ? handler_id === handler : entry.handler === (handler as EventHandlerCallable))) {\n this.handlers.delete(handler_id)\n this._removeIndexedHandler(entry.event_pattern, handler_id)\n this.scheduleMicrotask(() => {\n void this._onBusHandlersChange(entry, false)\n })\n }\n }\n }\n\n emit<T extends BaseEvent>(event: T): T {\n const original_event = event._event_original ?? event // if event is a bus-scoped proxy already, get the original underlying event object\n if (!original_event.bus) {\n // if we are the first bus to emit this event, set the bus property on the original event object\n original_event.bus = this\n }\n if (!Array.isArray(original_event.event_path)) {\n original_event.event_path = []\n }\n if (original_event._getDispatchContext() === undefined) {\n // when used in fastify/nextjs/other contexts with tracing based on AsyncLocalStorage in node\n // we want to capture the context at the emit site and use it when running handlers\n // because events may be handled async in a separate context than the emit site\n original_event._setDispatchContext(captureAsyncContext())\n }\n if (original_event.event_path.includes(this.label) || this._hasProcessedEvent(original_event)) {\n return this._getEventProxyScopedToThisBus(original_event) as T\n }\n\n if (!original_event.event_path.includes(this.label)) {\n original_event.event_path.push(this.label)\n }\n\n if (!original_event.event_parent_id && !original_event.event_emitted_by_handler_id) {\n this._resolveImplicitParentHandlerResult()?._linkEmittedChildEvent(original_event)\n }\n\n if (original_event.event_parent_id && original_event.event_emitted_by_handler_id) {\n const parent_result = original_event.event_parent?.event_results.get(original_event.event_emitted_by_handler_id)\n if (parent_result) {\n parent_result._linkEmittedChildEvent(original_event)\n }\n }\n\n if (\n this.event_history.max_history_size !== null &&\n this.event_history.max_history_size > 0 &&\n !this.event_history.max_history_drop &&\n this.event_history.size >= this.event_history.max_history_size\n ) {\n throw new Error(\n `${this.toString()}.emit(${original_event.event_type}) rejected: history limit reached (${this.event_history.size}/${this.event_history.max_history_size}); set event_history.max_history_drop=true to drop old history instead.`\n )\n }\n\n this.event_history.addEvent(original_event)\n this.event_history.trimEventHistory({\n is_event_complete: (candidate_event) => candidate_event.event_status === 'completed',\n on_remove: (candidate_event) => candidate_event._gc(),\n owner_label: this.toString(),\n max_history_size: this.event_history.max_history_size,\n max_history_drop: this.event_history.max_history_drop,\n })\n this._resolveFindWaiters(original_event)\n\n original_event.event_pending_bus_count += 1\n this.pending_event_queue.push(original_event)\n this._startRunloop()\n\n return this._getEventProxyScopedToThisBus(original_event) as T\n }\n\n // alias for emit\n dispatch<T extends BaseEvent>(event: T): T {\n return this.emit(event)\n }\n\n // find a recent event or wait for a future event that matches some criteria\n find(event_pattern: '*', options?: FindOptions<BaseEvent>): Promise<BaseEvent | null>\n find(event_pattern: '*', where: (event: BaseEvent) => boolean, options?: FindOptions<BaseEvent>): Promise<BaseEvent | null>\n find<T extends BaseEvent>(event_pattern: EventPattern<T>, options?: FindOptions<T>): Promise<T | null>\n find<T extends BaseEvent>(event_pattern: EventPattern<T>, where: (event: T) => boolean, options?: FindOptions<T>): Promise<T | null>\n async find<T extends BaseEvent>(\n event_pattern: EventPattern<T> | '*',\n where_or_options: ((event: T) => boolean) | FindOptions<T> = {},\n maybe_options: FindOptions<T> = {}\n ): Promise<T | null> {\n const where = typeof where_or_options === 'function' ? where_or_options : () => true\n const options = typeof where_or_options === 'function' ? maybe_options : where_or_options\n const match = await this.event_history.find(event_pattern as EventPattern<T> | '*', where, {\n ...options,\n event_is_child_of: (event, ancestor) => this.eventIsChildOf(event, ancestor),\n wait_for_future_match: (normalized_event_pattern, matches, future) =>\n this._waitForFutureMatch(normalized_event_pattern, matches, future),\n })\n if (!match) {\n return null\n }\n return this._getEventProxyScopedToThisBus(match) as T\n }\n\n private async _waitForFutureMatch(\n event_pattern: string | '*',\n matches: (event: BaseEvent) => boolean,\n future: boolean | number\n ): Promise<BaseEvent | null> {\n if (future === false) {\n return null\n }\n return await new Promise<BaseEvent | null>((resolve) => {\n const waiter: EphemeralFindEventHandler = {\n event_pattern,\n matches,\n resolve: (event) => resolve(event),\n }\n if (future !== true) {\n const timeout_ms = Math.max(0, Number(future)) * 1000\n waiter.timeout_id = setTimeout(() => {\n this.find_waiters.delete(waiter)\n resolve(null)\n }, timeout_ms)\n }\n this.find_waiters.add(waiter)\n })\n }\n\n async waitUntilIdle(timeout: number | null = null): Promise<boolean> {\n return await this.locks.waitForIdle(timeout)\n }\n\n // Weak idle check: only checks if handlers are idle, doesnt check that the queue is empty\n isIdle(): boolean {\n for (const event of this.event_history.values()) {\n for (const result of event.event_results.values()) {\n if (result.eventbus_id !== this.id) {\n continue\n }\n if (result.status === 'pending' || result.status === 'started') {\n return false\n }\n }\n }\n return true // no handlers are pending or started\n }\n\n // Stronger idle check: no queued work, no in-flight processing, _runloop not\n // active, and no handlers pending/running for this bus.\n isIdleAndQueueEmpty(): boolean {\n return this.pending_event_queue.length === 0 && this.in_flight_event_ids.size === 0 && this.isIdle() && !this.runloop_running\n }\n\n eventIsChildOf(child_event: BaseEvent, parent_event: BaseEvent): boolean {\n if (child_event.event_id === parent_event.event_id) {\n return false\n }\n\n let current_parent_id = child_event.event_parent_id\n while (current_parent_id) {\n if (current_parent_id === parent_event.event_id) {\n return true\n }\n const parent = this.event_history.get(current_parent_id)\n if (!parent) {\n return false\n }\n current_parent_id = parent.event_parent_id\n }\n return false\n }\n\n eventIsParentOf(parent_event: BaseEvent, child_event: BaseEvent): boolean {\n return this.eventIsChildOf(child_event, parent_event)\n }\n\n // return a full detailed tree diagram of all events and results on this bus\n logTree(): string {\n return logTree(this)\n }\n\n // Resolve an event id from this bus first, then across all known buses.\n findEventById(event_id: string): BaseEvent | null {\n return this.event_history.get(event_id) ?? this.all_instances.findEventById(event_id)\n }\n\n // Walk up the parent event chain to find an in-flight ancestor handler result.\n // Returns the result if found, null otherwise. Used by _processEventImmediately to detect\n // cross-bus queue-jump scenarios where the calling handler is on a different bus.\n _getParentEventResultAcrossAllBuses(event: BaseEvent): EventResult | null {\n const original = event._event_original ?? event\n let current_parent_id = original.event_parent_id\n let current_handler_id = original.event_emitted_by_handler_id\n while (current_handler_id && current_parent_id) {\n const parent = this.all_instances.findEventById(current_parent_id)\n if (!parent) break\n const handler_result = parent.event_results.get(current_handler_id)\n if (handler_result && handler_result.status === 'started') return handler_result\n current_parent_id = parent.event_parent_id\n current_handler_id = parent.event_emitted_by_handler_id\n }\n return null\n }\n\n private _startRunloop(): void {\n if (this.runloop_running) {\n return\n }\n this.runloop_running = true\n this.scheduleMicrotask(() => {\n void this._runloop()\n })\n }\n\n // schedule the processing of an event on the event bus by its normal _runloop\n // optionally using a pre-acquired lock if we're inside handling of a parent event\n private async _processEvent(\n event: BaseEvent,\n options: {\n bypass_event_locks?: boolean\n pre_acquired_lock?: AsyncLock | null\n } = {}\n ): Promise<void> {\n let pending_entries: Array<{\n handler: EventHandler\n result: EventResult\n }> = []\n try {\n if (this._hasProcessedEvent(event)) {\n return\n }\n const scoped_event = this._getEventProxyScopedToThisBus(event)\n await this._onEventChange(scoped_event, 'pending')\n event._markStarted()\n pending_entries = event._createPendingHandlerResults(this)\n const resolved_event_timeout = event.event_timeout ?? this.event_timeout\n if (this.middlewares.length > 0) {\n for (const entry of pending_entries) {\n await this._onEventResultChange(scoped_event, entry.result, 'pending')\n }\n }\n await this.locks._runWithEventLock(\n event,\n () =>\n this._runHandlersWithTimeout(event, pending_entries, resolved_event_timeout, () =>\n _runWithSlowMonitor(event._createSlowEventWarningTimer(), () => scoped_event._runHandlers(pending_entries))\n ),\n options\n )\n this._markEventCompletedIfNeeded(event)\n } finally {\n if (options.pre_acquired_lock) {\n options.pre_acquired_lock.release()\n }\n this.in_flight_event_ids.delete(event.event_id)\n this.locks._notifyIdleListeners()\n }\n }\n\n // Called when a handler does `await child.done()` \u2014 processes the child event\n // immediately (\"queue-jump\") instead of waiting for the _runloop to pick it up.\n //\n // Yield-and-reacquire: if the calling handler holds a handler concurrency lock,\n // we temporarily release it so child handlers on the same bus can acquire it\n // (preventing deadlock for serial handler mode). We re-acquire after\n // the child completes so the parent handler can continue with the lock held.\n async _processEventImmediately<T extends BaseEvent>(event: T, handler_result?: EventResult): Promise<T> {\n const original_event = event._event_original ?? event\n // Find the parent handler's result: prefer the proxy-provided one (only if\n // the handler is still running), then this bus's stack, then walk up the\n // parent event tree (cross-bus case). If none found, we're not inside a\n // handler and should fall back to eventCompleted().\n const proxy_result = handler_result?.status === 'started' ? handler_result : undefined\n const currently_active_event_result =\n proxy_result ?? this.locks._getActiveHandlerResult() ?? this._getParentEventResultAcrossAllBuses(original_event) ?? undefined\n if (!currently_active_event_result) {\n // Not inside any handler scope \u2014 avoid queue-jump, but if this event is\n // next in line we can process it immediately without waiting on the _runloop.\n // We must acquire/revalidate the event lock first to avoid racing the runloop\n // and accidentally reordering/removing the wrong queue head.\n const queue_index = this.pending_event_queue.indexOf(original_event)\n const can_process_now =\n queue_index === 0 &&\n !this.locks._isPaused() &&\n !this.in_flight_event_ids.has(original_event.event_id) &&\n !this._hasProcessedEvent(original_event)\n if (can_process_now) {\n const event_lock = this.locks.getLockForEvent(original_event)\n let pre_acquired_lock: AsyncLock | null = null\n if (event_lock) {\n await event_lock.acquire()\n pre_acquired_lock = event_lock\n }\n const queue_head = this.pending_event_queue[0]\n const queue_head_original = queue_head?._event_original ?? queue_head\n const still_can_process_now =\n queue_head_original === original_event &&\n !this.locks._isPaused() &&\n !this.in_flight_event_ids.has(original_event.event_id) &&\n !this._hasProcessedEvent(original_event)\n if (still_can_process_now) {\n this.pending_event_queue.shift()\n this.in_flight_event_ids.add(original_event.event_id)\n await this._processEvent(original_event, {\n bypass_event_locks: true,\n pre_acquired_lock,\n })\n if (original_event.event_status !== 'completed') {\n await original_event.eventCompleted()\n }\n return event\n }\n if (pre_acquired_lock) {\n pre_acquired_lock.release()\n }\n }\n await original_event.eventCompleted()\n return event\n }\n\n // ensure a pause request is set so the bus _runloop pauses and (will resume when the handler exits)\n currently_active_event_result._ensureQueueJumpPause(this)\n if (original_event.event_status === 'completed') {\n return event\n }\n\n // re-endter event-level handler lock if needed\n if (currently_active_event_result._lock) {\n await currently_active_event_result._lock.runQueueJump(this._processEventImmediatelyAcrossBuses.bind(this, original_event))\n return event\n }\n\n await this._processEventImmediatelyAcrossBuses(original_event)\n return event\n }\n\n // Processes a queue-jumped event across all buses that have it emitted.\n // Called from _processEventImmediately after the parent handler's lock has been yielded.\n private async _processEventImmediatelyAcrossBuses(event: BaseEvent): Promise<void> {\n // Use event_path ordering to pick candidate buses and filter out buses that\n // haven't seen the event or already processed it.\n const ordered: EventBus[] = []\n const seen = new Set<EventBus>()\n const event_path = Array.isArray(event.event_path) ? event.event_path : []\n for (const label of event_path) {\n for (const bus of this.all_instances) {\n if (bus.label !== label) {\n continue\n }\n if (!bus.event_history.has(event.event_id)) {\n continue\n }\n if (bus._hasProcessedEvent(event)) {\n continue\n }\n if (!seen.has(bus)) {\n ordered.push(bus)\n seen.add(bus)\n }\n }\n }\n if (!seen.has(this) && this.event_history.has(event.event_id)) {\n ordered.push(this)\n }\n if (ordered.length === 0) {\n await event.eventCompleted()\n return\n }\n\n // Determine which event lock the initiating bus resolves to, so we can\n // detect when other buses share the same instance (global-serial).\n const initiating_event_lock = this.locks.getLockForEvent(event)\n const pause_releases: Array<() => void> = []\n\n try {\n for (const bus of ordered) {\n if (bus !== this) {\n pause_releases.push(bus.locks._requestRunloopPause())\n }\n }\n\n for (const bus of ordered) {\n const index = bus.pending_event_queue.indexOf(event)\n if (index >= 0) {\n bus.pending_event_queue.splice(index, 1)\n }\n if (bus._hasProcessedEvent(event)) {\n continue\n }\n if (bus.in_flight_event_ids.has(event.event_id)) {\n continue\n }\n bus.in_flight_event_ids.add(event.event_id)\n\n // Bypass event lock on the initiating bus (we're already inside a handler\n // that acquired it). For other buses, only bypass if they resolve to the same\n // lock instance (global-serial shares one lock across all buses).\n const bus_event_lock = bus.locks.getLockForEvent(event)\n const should_bypass_event_lock = bus === this || (initiating_event_lock !== null && bus_event_lock === initiating_event_lock)\n\n await bus._processEvent(event, {\n bypass_event_locks: should_bypass_event_lock,\n })\n }\n\n if (event.event_status !== 'completed') {\n await event.eventCompleted()\n }\n } finally {\n for (const release of pause_releases) {\n release()\n }\n }\n }\n\n private async _runloop(): Promise<void> {\n for (;;) {\n while (this.pending_event_queue.length > 0) {\n await Promise.resolve()\n if (this.locks._isPaused()) {\n await this.locks._waitUntilRunloopResumed()\n continue\n }\n const next_event = this.pending_event_queue[0]\n if (!next_event) {\n continue\n }\n const original_event = next_event._event_original ?? next_event\n if (this._hasProcessedEvent(original_event)) {\n this.pending_event_queue.shift()\n continue\n }\n let pre_acquired_lock: AsyncLock | null = null\n const event_lock = this.locks.getLockForEvent(original_event)\n if (event_lock) {\n await event_lock.acquire()\n pre_acquired_lock = event_lock\n }\n // Queue head may have changed while waiting for the lock\n // (e.g. done() processing the head immediately). Revalidate\n // before mutating the queue to avoid removing the wrong event.\n const current_head = this.pending_event_queue[0]\n const current_head_original = current_head?._event_original ?? current_head\n if (current_head_original !== original_event) {\n if (pre_acquired_lock) {\n pre_acquired_lock.release()\n }\n continue\n }\n this.pending_event_queue.shift()\n if (this.in_flight_event_ids.has(original_event.event_id)) {\n if (pre_acquired_lock) {\n pre_acquired_lock.release()\n }\n continue\n }\n this.in_flight_event_ids.add(original_event.event_id)\n void this._processEvent(original_event, {\n bypass_event_locks: true,\n pre_acquired_lock,\n })\n await Promise.resolve()\n }\n this.runloop_running = false\n if (this.pending_event_queue.length > 0) {\n this._startRunloop()\n return\n }\n this.locks._notifyIdleListeners()\n return\n }\n }\n\n // check if an event has been processed (and completed) by this bus\n _hasProcessedEvent(event: BaseEvent): boolean {\n const results = Array.from(event.event_results.values()).filter((result) => result.eventbus_id === this.id)\n if (results.length === 0) {\n return false\n }\n return results.every((result) => result.status === 'completed' || result.status === 'error')\n }\n\n private _resolveImplicitParentHandlerResult(): EventResult | null {\n const active_on_target_bus = this.locks._getActiveHandlerResults().filter((result) => result.status === 'started')\n if (active_on_target_bus.length === 1) {\n return active_on_target_bus[0]\n }\n\n const active_globally: EventResult[] = []\n for (const bus of this.all_instances) {\n for (const result of bus.locks._getActiveHandlerResults()) {\n if (result.status === 'started') {\n active_globally.push(result)\n }\n }\n }\n if (active_globally.length === 1) {\n return active_globally[0]\n }\n return null\n }\n\n // get a proxy wrapper around an Event that will automatically link emitted child events to this bus and handler\n // proxy is what gets passed into the handler, if handler does event.bus.emit(...) to dispatch child events,\n // the proxy auto-sets event.parent_event_id and event.event_emitted_by_handler_id\n _getEventProxyScopedToThisBus<T extends BaseEvent>(event: T, handler_result?: EventResult): T {\n const original_event = event._event_original ?? event\n const bus = this\n const parent_event_id = original_event.event_id\n const bus_proxy = new Proxy(bus, {\n get(target, prop, receiver) {\n if (prop === '_processEventImmediately') {\n const runner = Reflect.get(target, prop, receiver) as EventBus['_processEventImmediately']\n const process_event_immediately = <TChild extends BaseEvent>(child_event: TChild): Promise<TChild> => {\n return runner.call(target, child_event, handler_result) as Promise<TChild>\n }\n return process_event_immediately\n }\n if (prop === 'dispatch' || prop === 'emit') {\n const emit_child_event = <TChild extends BaseEvent>(child_event: TChild): TChild => {\n const original_child = child_event._event_original ?? child_event\n if (handler_result) {\n handler_result._linkEmittedChildEvent(original_child)\n } else if (!original_child.event_parent_id && original_child.event_id !== parent_event_id) {\n // fallback for non-handler scoped emit/dispatch\n original_child.event_parent_id = parent_event_id\n }\n const dispatcher = Reflect.get(target, prop, receiver) as EventBus['dispatch']\n const dispatched = dispatcher.call(target, original_child)\n return target._getEventProxyScopedToThisBus(dispatched as TChild, handler_result)\n }\n return emit_child_event\n }\n return Reflect.get(target, prop, receiver)\n },\n })\n const scoped = new Proxy(original_event, {\n get(target, prop, receiver) {\n if (prop === 'bus') {\n return bus_proxy\n }\n if (prop === '_event_original') {\n return target\n }\n return Reflect.get(target, prop, receiver)\n },\n set(target, prop, value) {\n if (prop === 'bus') {\n return true\n }\n return Reflect.set(target, prop, value, target)\n },\n has(target, prop) {\n if (prop === 'bus') {\n return true\n }\n if (prop === '_event_original') {\n return true\n }\n return Reflect.has(target, prop)\n },\n })\n\n return scoped as T\n }\n\n private _resolveFindWaiters(event: BaseEvent): void {\n for (const waiter of Array.from(this.find_waiters)) {\n if ((waiter.event_pattern !== '*' && event.event_type !== waiter.event_pattern) || !waiter.matches(event)) {\n continue\n }\n if (waiter.timeout_id) {\n clearTimeout(waiter.timeout_id)\n }\n this.find_waiters.delete(waiter)\n waiter.resolve(event)\n }\n }\n\n _getHandlersForEvent(event: BaseEvent): EventHandler[] {\n const handlers: EventHandler[] = []\n for (const key of [event.event_type, '*']) {\n const ids = this.handlers_by_key.get(key)\n if (!ids) continue\n for (const id of ids) {\n const entry = this.handlers.get(id)\n if (entry) handlers.push(entry)\n }\n }\n return handlers\n }\n\n private _removeIndexedHandler(event_pattern: string | '*', handler_id: string): void {\n const ids = this.handlers_by_key.get(event_pattern)\n if (!ids) return\n const idx = ids.indexOf(handler_id)\n if (idx < 0) return\n ids.splice(idx, 1)\n if (ids.length === 0) this.handlers_by_key.delete(event_pattern)\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,279 @@
1
+ import { z } from "zod";
2
+ import { v5 as uuidv5 } from "uuid";
3
+ import { normalizeEventPattern } from "./types.js";
4
+ import { monotonicDatetime } from "./helpers.js";
5
+ const HANDLER_ID_NAMESPACE = uuidv5("bubus-handler", uuidv5.DNS);
6
+ const FindWaiterJSONSchema = z.object({
7
+ event_pattern: z.union([z.string(), z.literal("*")]),
8
+ has_timeout: z.boolean()
9
+ }).strict();
10
+ class FindWaiter {
11
+ static toJSON(waiter) {
12
+ return {
13
+ event_pattern: waiter.event_pattern,
14
+ has_timeout: waiter.timeout_id !== void 0
15
+ };
16
+ }
17
+ static fromJSON(data, overrides = {}) {
18
+ const record = FindWaiterJSONSchema.parse(data);
19
+ const event_pattern = record.event_pattern;
20
+ const defaultMatches = (event) => event_pattern === "*" || event.event_type === event_pattern;
21
+ return {
22
+ event_pattern,
23
+ matches: overrides.matches ?? defaultMatches,
24
+ resolve: overrides.resolve ?? (() => {
25
+ })
26
+ };
27
+ }
28
+ static toJSONArray(waiters) {
29
+ return Array.from(waiters, (waiter) => FindWaiter.toJSON(waiter));
30
+ }
31
+ static fromJSONArray(data, overrides = {}) {
32
+ if (!Array.isArray(data)) {
33
+ return [];
34
+ }
35
+ return data.map((item) => FindWaiter.fromJSON(item, overrides));
36
+ }
37
+ }
38
+ const EventHandlerJSONSchema = z.object({
39
+ id: z.string(),
40
+ eventbus_name: z.string(),
41
+ eventbus_id: z.string().uuid(),
42
+ event_pattern: z.union([z.string(), z.literal("*")]),
43
+ handler_name: z.string(),
44
+ handler_file_path: z.string().nullable().optional(),
45
+ handler_timeout: z.number().nullable().optional(),
46
+ handler_slow_timeout: z.number().nullable().optional(),
47
+ handler_registered_at: z.string().datetime()
48
+ }).strict();
49
+ class EventHandler {
50
+ id;
51
+ // unique uuidv5 based on hash of bus name, handler name, handler file path:lineno, registered at timestamp, and event key
52
+ handler;
53
+ // original callable passed to on()
54
+ handler_name;
55
+ // name of the handler function, or 'anonymous' if the handler is an anonymous/arrow function
56
+ handler_file_path;
57
+ // ~/path/to/source/file.ts:123, or null when unknown
58
+ handler_timeout;
59
+ // maximum time in seconds that the handler is allowed to run before it is aborted, resolved at runtime if not set
60
+ handler_slow_timeout;
61
+ // warning threshold in seconds for slow handler execution
62
+ handler_registered_at;
63
+ // ISO datetime used in the deterministic handler-id seed
64
+ event_pattern;
65
+ // event_type string to match against, or '*' to match all events
66
+ eventbus_name;
67
+ // name of the event bus that the handler is registered on
68
+ eventbus_id;
69
+ // uuidv7 identifier of the event bus that the handler is registered on
70
+ constructor(params) {
71
+ const handler_registered_at = monotonicDatetime(params.handler_registered_at);
72
+ this.id = params.id ?? EventHandler.computeHandlerId({
73
+ eventbus_id: params.eventbus_id,
74
+ handler_name: params.handler_name,
75
+ handler_file_path: params.handler_file_path,
76
+ handler_registered_at,
77
+ event_pattern: params.event_pattern
78
+ });
79
+ this.handler = params.handler;
80
+ this.handler_name = params.handler_name;
81
+ this.handler_file_path = params.handler_file_path ?? null;
82
+ this.handler_timeout = params.handler_timeout;
83
+ this.handler_slow_timeout = params.handler_slow_timeout;
84
+ this.handler_registered_at = handler_registered_at;
85
+ this.event_pattern = params.event_pattern;
86
+ this.eventbus_name = params.eventbus_name;
87
+ this.eventbus_id = params.eventbus_id;
88
+ }
89
+ get _handler_async() {
90
+ const handler = this.handler;
91
+ if (Object.prototype.toString.call(handler) === "[object AsyncFunction]") {
92
+ return handler;
93
+ }
94
+ return async (event) => await handler(event);
95
+ }
96
+ // compute globally unique handler uuid as a hash of the bus name, handler name, handler file path, registered at timestamp, and event key
97
+ static computeHandlerId(params) {
98
+ const file_path = params.handler_file_path ?? "unknown";
99
+ const seed = `${params.eventbus_id}|${params.handler_name}|${file_path}|${params.handler_registered_at}|${params.event_pattern}`;
100
+ return uuidv5(seed, HANDLER_ID_NAMESPACE);
101
+ }
102
+ static fromCallable(params) {
103
+ const entry = new EventHandler({
104
+ id: params.id,
105
+ handler: params.handler,
106
+ handler_name: params.handler.name || "anonymous",
107
+ handler_file_path: params.handler_file_path ?? null,
108
+ handler_timeout: params.handler_timeout,
109
+ handler_slow_timeout: params.handler_slow_timeout,
110
+ handler_registered_at: monotonicDatetime(params.handler_registered_at),
111
+ event_pattern: normalizeEventPattern(params.event_pattern),
112
+ eventbus_name: params.eventbus_name,
113
+ eventbus_id: params.eventbus_id
114
+ });
115
+ const should_detect_handler_file_path = params.detect_handler_file_path ?? true;
116
+ if (should_detect_handler_file_path && entry.handler_file_path === null) {
117
+ entry._detectHandlerFilePath();
118
+ if (params.id === void 0) {
119
+ entry.id = EventHandler.computeHandlerId({
120
+ eventbus_id: entry.eventbus_id,
121
+ handler_name: entry.handler_name,
122
+ handler_file_path: entry.handler_file_path,
123
+ handler_registered_at: entry.handler_registered_at,
124
+ event_pattern: entry.event_pattern
125
+ });
126
+ }
127
+ }
128
+ return entry;
129
+ }
130
+ // "someHandlerName() @ ~/path/to/source/file.ts:123" <- best case when file path is available and its a named function
131
+ // "function#1234()" <- worst case when no file path is available and its an anonymous/arrow function defined inline
132
+ toString() {
133
+ const label = this.handler_name && this.handler_name !== "anonymous" ? `${this.handler_name}()` : `function#${this.id.slice(-4)}()`;
134
+ return this.handler_file_path ? `${label} @ ${this.handler_file_path}` : label;
135
+ }
136
+ // autodetect the path/to/source/file.ts:lineno where the handler is defined for better logs
137
+ // optional (controlled by EventBus.event_handler_detect_file_paths) because it can slow down performance to introspect stack traces and find file paths
138
+ _detectHandlerFilePath() {
139
+ const line = new Error().stack?.split("\n").map((l) => l.trim()).filter(Boolean)[4];
140
+ if (!line) return;
141
+ const resolved_path = line.trim().match(/\(([^)]+)\)$/)?.[1] ?? line.trim().match(/^\s*at\s+(.+)$/)?.[1] ?? line.trim().match(/^[^@]+@(.+)$/)?.[1] ?? line.trim();
142
+ const match = resolved_path.match(/^(.*?):(\d+)(?::\d+)?$/);
143
+ let normalized = match ? match[1] : resolved_path;
144
+ const line_number = match?.[2];
145
+ if (normalized.startsWith("file://")) {
146
+ let path = normalized.slice("file://".length);
147
+ if (path.startsWith("localhost/")) path = path.slice("localhost".length);
148
+ if (!path.startsWith("/")) path = `/${path}`;
149
+ try {
150
+ normalized = decodeURIComponent(path);
151
+ } catch {
152
+ normalized = path;
153
+ }
154
+ }
155
+ normalized = normalized.replace(/\/users\/[^/]+\//i, "~/").replace(/\/home\/[^/]+\//i, "~/");
156
+ this.handler_file_path = line_number ? `${normalized}:${line_number}` : normalized;
157
+ }
158
+ toJSON() {
159
+ return {
160
+ id: this.id,
161
+ eventbus_name: this.eventbus_name,
162
+ eventbus_id: this.eventbus_id,
163
+ event_pattern: this.event_pattern,
164
+ handler_name: this.handler_name,
165
+ handler_file_path: this.handler_file_path,
166
+ handler_timeout: this.handler_timeout,
167
+ handler_slow_timeout: this.handler_slow_timeout,
168
+ handler_registered_at: this.handler_registered_at
169
+ };
170
+ }
171
+ static fromJSON(data, handler) {
172
+ const record = EventHandlerJSONSchema.parse(data);
173
+ const handler_fn = handler ?? (() => void 0);
174
+ const handler_name = record.handler_name || handler_fn.name || "anonymous";
175
+ return new EventHandler({
176
+ id: record.id,
177
+ handler: handler_fn,
178
+ handler_name,
179
+ handler_file_path: record.handler_file_path ?? null,
180
+ handler_timeout: record.handler_timeout,
181
+ handler_slow_timeout: record.handler_slow_timeout,
182
+ handler_registered_at: record.handler_registered_at,
183
+ event_pattern: record.event_pattern,
184
+ eventbus_name: record.eventbus_name,
185
+ eventbus_id: record.eventbus_id
186
+ });
187
+ }
188
+ static toJSONArray(handlers) {
189
+ return Array.from(handlers, (handler) => handler.toJSON());
190
+ }
191
+ static fromJSONArray(data, handler) {
192
+ if (!Array.isArray(data)) {
193
+ return [];
194
+ }
195
+ return data.map((item) => EventHandler.fromJSON(item, handler));
196
+ }
197
+ get eventbus_label() {
198
+ return `${this.eventbus_name}#${this.eventbus_id.slice(-4)}`;
199
+ }
200
+ }
201
+ class TimeoutError extends Error {
202
+ constructor(message) {
203
+ super(message);
204
+ this.name = "TimeoutError";
205
+ }
206
+ }
207
+ class EventHandlerError extends Error {
208
+ event_result;
209
+ timeout_seconds;
210
+ cause;
211
+ constructor(message, params) {
212
+ super(message);
213
+ this.name = "EventHandlerError";
214
+ this.event_result = params.event_result;
215
+ this.cause = params.cause;
216
+ this.timeout_seconds = params.timeout_seconds ?? this.event_result.event.event_timeout ?? null;
217
+ }
218
+ get event() {
219
+ return this.event_result.event;
220
+ }
221
+ get event_type() {
222
+ return this.event.event_type;
223
+ }
224
+ get handler_name() {
225
+ return this.event_result.handler_name;
226
+ }
227
+ get handler_id() {
228
+ return this.event_result.handler_id;
229
+ }
230
+ get event_timeout() {
231
+ return this.event.event_timeout;
232
+ }
233
+ }
234
+ class EventHandlerTimeoutError extends EventHandlerError {
235
+ constructor(message, params) {
236
+ super(message, {
237
+ event_result: params.event_result,
238
+ timeout_seconds: params.timeout_seconds,
239
+ cause: params.cause ?? new TimeoutError(message)
240
+ });
241
+ this.name = "EventHandlerTimeoutError";
242
+ }
243
+ }
244
+ class EventHandlerCancelledError extends EventHandlerError {
245
+ constructor(message, params) {
246
+ super(message, params);
247
+ this.name = "EventHandlerCancelledError";
248
+ }
249
+ }
250
+ class EventHandlerAbortedError extends EventHandlerError {
251
+ constructor(message, params) {
252
+ super(message, params);
253
+ this.name = "EventHandlerAbortedError";
254
+ }
255
+ }
256
+ class EventHandlerResultSchemaError extends EventHandlerError {
257
+ raw_value;
258
+ constructor(message, params) {
259
+ super(message, params);
260
+ this.name = "EventHandlerResultSchemaError";
261
+ this.raw_value = params.raw_value;
262
+ }
263
+ get expected_schema() {
264
+ return this.event_result.event.event_result_type;
265
+ }
266
+ }
267
+ export {
268
+ EventHandler,
269
+ EventHandlerAbortedError,
270
+ EventHandlerCancelledError,
271
+ EventHandlerError,
272
+ EventHandlerJSONSchema,
273
+ EventHandlerResultSchemaError,
274
+ EventHandlerTimeoutError,
275
+ FindWaiter,
276
+ FindWaiterJSONSchema,
277
+ TimeoutError
278
+ };
279
+ //# sourceMappingURL=event_handler.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/event_handler.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { v5 as uuidv5 } from 'uuid'\n\nimport { normalizeEventPattern, type EventHandlerCallable, type EventPattern } from './types.js'\nimport { BaseEvent } from './base_event.js'\nimport type { EventResult } from './event_result.js'\nimport { monotonicDatetime } from './helpers.js'\n\nconst HANDLER_ID_NAMESPACE = uuidv5('bubus-handler', uuidv5.DNS)\n\nexport type EphemeralFindEventHandler = {\n // Similar to a handler, except it's for .find() calls.\n // Resolved on dispatch, ephemeral, and never shows up in the processing tree.\n event_pattern: string | '*'\n matches: (event: BaseEvent) => boolean\n resolve: (event: BaseEvent) => void\n timeout_id?: ReturnType<typeof setTimeout>\n}\n\nexport const FindWaiterJSONSchema = z\n .object({\n event_pattern: z.union([z.string(), z.literal('*')]),\n has_timeout: z.boolean(),\n })\n .strict()\n\nexport type FindWaiterJSON = z.infer<typeof FindWaiterJSONSchema>\n\nexport class FindWaiter {\n static toJSON(waiter: EphemeralFindEventHandler): FindWaiterJSON {\n return {\n event_pattern: waiter.event_pattern,\n has_timeout: waiter.timeout_id !== undefined,\n }\n }\n\n static fromJSON(\n data: unknown,\n overrides: {\n matches?: (event: BaseEvent) => boolean\n resolve?: (event: BaseEvent) => void\n } = {}\n ): EphemeralFindEventHandler {\n const record = FindWaiterJSONSchema.parse(data)\n const event_pattern = record.event_pattern\n const defaultMatches = (event: BaseEvent): boolean => event_pattern === '*' || event.event_type === event_pattern\n return {\n event_pattern,\n matches: overrides.matches ?? defaultMatches,\n resolve: overrides.resolve ?? (() => {}),\n }\n }\n\n static toJSONArray(waiters: Iterable<EphemeralFindEventHandler>): FindWaiterJSON[] {\n return Array.from(waiters, (waiter) => FindWaiter.toJSON(waiter))\n }\n\n static fromJSONArray(\n data: unknown,\n overrides: {\n matches?: (event: BaseEvent) => boolean\n resolve?: (event: BaseEvent) => void\n } = {}\n ): EphemeralFindEventHandler[] {\n if (!Array.isArray(data)) {\n return []\n }\n return data.map((item) => FindWaiter.fromJSON(item, overrides))\n }\n}\n\nexport const EventHandlerJSONSchema = z\n .object({\n id: z.string(),\n eventbus_name: z.string(),\n eventbus_id: z.string().uuid(),\n event_pattern: z.union([z.string(), z.literal('*')]),\n handler_name: z.string(),\n handler_file_path: z.string().nullable().optional(),\n handler_timeout: z.number().nullable().optional(),\n handler_slow_timeout: z.number().nullable().optional(),\n handler_registered_at: z.string().datetime(),\n })\n .strict()\n\nexport type EventHandlerJSON = z.infer<typeof EventHandlerJSONSchema>\n\n// an entry in the list of event handlers that are registered on a bus\nexport class EventHandler {\n id: string // unique uuidv5 based on hash of bus name, handler name, handler file path:lineno, registered at timestamp, and event key\n handler: EventHandlerCallable // original callable passed to on()\n handler_name: string // name of the handler function, or 'anonymous' if the handler is an anonymous/arrow function\n handler_file_path: string | null // ~/path/to/source/file.ts:123, or null when unknown\n handler_timeout?: number | null // maximum time in seconds that the handler is allowed to run before it is aborted, resolved at runtime if not set\n handler_slow_timeout?: number | null // warning threshold in seconds for slow handler execution\n handler_registered_at: string // ISO datetime used in the deterministic handler-id seed\n event_pattern: string | '*' // event_type string to match against, or '*' to match all events\n eventbus_name: string // name of the event bus that the handler is registered on\n eventbus_id: string // uuidv7 identifier of the event bus that the handler is registered on\n\n constructor(params: {\n id?: string\n handler: EventHandlerCallable\n handler_name: string\n handler_file_path?: string | null\n handler_timeout?: number | null\n handler_slow_timeout?: number | null\n handler_registered_at: string\n event_pattern: string | '*'\n eventbus_name: string\n eventbus_id: string\n }) {\n const handler_registered_at = monotonicDatetime(params.handler_registered_at)\n this.id =\n params.id ??\n EventHandler.computeHandlerId({\n eventbus_id: params.eventbus_id,\n handler_name: params.handler_name,\n handler_file_path: params.handler_file_path,\n handler_registered_at,\n event_pattern: params.event_pattern,\n })\n this.handler = params.handler\n this.handler_name = params.handler_name\n this.handler_file_path = params.handler_file_path ?? null\n this.handler_timeout = params.handler_timeout\n this.handler_slow_timeout = params.handler_slow_timeout\n this.handler_registered_at = handler_registered_at\n this.event_pattern = params.event_pattern\n this.eventbus_name = params.eventbus_name\n this.eventbus_id = params.eventbus_id\n }\n\n get _handler_async(): EventHandlerCallable {\n const handler = this.handler\n if (Object.prototype.toString.call(handler) === '[object AsyncFunction]') {\n return handler\n }\n return async (event: BaseEvent) => await handler(event)\n }\n\n // compute globally unique handler uuid as a hash of the bus name, handler name, handler file path, registered at timestamp, and event key\n static computeHandlerId(params: {\n eventbus_id: string\n handler_name: string\n handler_file_path?: string | null\n handler_registered_at: string\n event_pattern: string | '*'\n }): string {\n const file_path = params.handler_file_path ?? 'unknown'\n const seed = `${params.eventbus_id}|${params.handler_name}|${file_path}|${params.handler_registered_at}|${params.event_pattern}`\n return uuidv5(seed, HANDLER_ID_NAMESPACE)\n }\n\n static fromCallable<TEvent extends BaseEvent = BaseEvent>(params: {\n handler: EventHandlerCallable<TEvent>\n event_pattern: EventPattern | '*'\n eventbus_name: string\n eventbus_id: string\n detect_handler_file_path?: boolean\n id?: string\n handler_file_path?: string | null\n handler_timeout?: number | null\n handler_slow_timeout?: number | null\n handler_registered_at?: string\n }): EventHandler {\n const entry = new EventHandler({\n id: params.id,\n handler: params.handler as EventHandlerCallable,\n handler_name: params.handler.name || 'anonymous',\n handler_file_path: params.handler_file_path ?? null,\n handler_timeout: params.handler_timeout,\n handler_slow_timeout: params.handler_slow_timeout,\n handler_registered_at: monotonicDatetime(params.handler_registered_at),\n event_pattern: normalizeEventPattern(params.event_pattern),\n eventbus_name: params.eventbus_name,\n eventbus_id: params.eventbus_id,\n })\n const should_detect_handler_file_path = params.detect_handler_file_path ?? true\n if (should_detect_handler_file_path && entry.handler_file_path === null) {\n entry._detectHandlerFilePath()\n if (params.id === undefined) {\n entry.id = EventHandler.computeHandlerId({\n eventbus_id: entry.eventbus_id,\n handler_name: entry.handler_name,\n handler_file_path: entry.handler_file_path,\n handler_registered_at: entry.handler_registered_at,\n event_pattern: entry.event_pattern,\n })\n }\n }\n return entry\n }\n\n // \"someHandlerName() @ ~/path/to/source/file.ts:123\" <- best case when file path is available and its a named function\n // \"function#1234()\" <- worst case when no file path is available and its an anonymous/arrow function defined inline\n toString(): string {\n const label = this.handler_name && this.handler_name !== 'anonymous' ? `${this.handler_name}()` : `function#${this.id.slice(-4)}()`\n return this.handler_file_path ? `${label} @ ${this.handler_file_path}` : label\n }\n\n // autodetect the path/to/source/file.ts:lineno where the handler is defined for better logs\n // optional (controlled by EventBus.event_handler_detect_file_paths) because it can slow down performance to introspect stack traces and find file paths\n _detectHandlerFilePath(): void {\n const line = new Error().stack\n ?.split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)[4]\n if (!line) return\n const resolved_path =\n line.trim().match(/\\(([^)]+)\\)$/)?.[1] ??\n line.trim().match(/^\\s*at\\s+(.+)$/)?.[1] ??\n line.trim().match(/^[^@]+@(.+)$/)?.[1] ??\n line.trim()\n const match = resolved_path.match(/^(.*?):(\\d+)(?::\\d+)?$/)\n let normalized = match ? match[1] : resolved_path\n const line_number = match?.[2]\n if (normalized.startsWith('file://')) {\n let path = normalized.slice('file://'.length)\n if (path.startsWith('localhost/')) path = path.slice('localhost'.length)\n if (!path.startsWith('/')) path = `/${path}`\n try {\n normalized = decodeURIComponent(path)\n } catch {\n normalized = path\n }\n }\n normalized = normalized.replace(/\\/users\\/[^/]+\\//i, '~/').replace(/\\/home\\/[^/]+\\//i, '~/')\n this.handler_file_path = line_number ? `${normalized}:${line_number}` : normalized\n }\n\n toJSON(): EventHandlerJSON {\n return {\n id: this.id,\n eventbus_name: this.eventbus_name,\n eventbus_id: this.eventbus_id,\n event_pattern: this.event_pattern,\n handler_name: this.handler_name,\n handler_file_path: this.handler_file_path,\n handler_timeout: this.handler_timeout,\n handler_slow_timeout: this.handler_slow_timeout,\n handler_registered_at: this.handler_registered_at,\n }\n }\n\n static fromJSON(data: unknown, handler?: EventHandlerCallable): EventHandler {\n const record = EventHandlerJSONSchema.parse(data)\n const handler_fn = handler ?? ((() => undefined) as EventHandlerCallable)\n const handler_name = record.handler_name || handler_fn.name || 'anonymous' // 'anonymous' is the default name for anonymous/arrow functions\n return new EventHandler({\n id: record.id,\n handler: handler_fn,\n handler_name,\n handler_file_path: record.handler_file_path ?? null,\n handler_timeout: record.handler_timeout,\n handler_slow_timeout: record.handler_slow_timeout,\n handler_registered_at: record.handler_registered_at,\n event_pattern: record.event_pattern,\n eventbus_name: record.eventbus_name,\n eventbus_id: record.eventbus_id,\n })\n }\n\n static toJSONArray(handlers: Iterable<EventHandler>): EventHandlerJSON[] {\n return Array.from(handlers, (handler) => handler.toJSON())\n }\n\n static fromJSONArray(data: unknown, handler?: EventHandlerCallable): EventHandler[] {\n if (!Array.isArray(data)) {\n return []\n }\n return data.map((item) => EventHandler.fromJSON(item, handler))\n }\n\n get eventbus_label(): string {\n return `${this.eventbus_name}#${this.eventbus_id.slice(-4)}`\n }\n}\n\n// Generic base TimeoutError used for EventHandlerTimeoutError.cause default value if\nexport class TimeoutError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'TimeoutError'\n }\n}\n\n// Base class for all errors that can occur while running an event handler\nexport class EventHandlerError extends Error {\n event_result: EventResult\n timeout_seconds: number | null\n cause: Error\n\n constructor(message: string, params: { event_result: EventResult; timeout_seconds?: number | null; cause: Error }) {\n super(message)\n this.name = 'EventHandlerError'\n this.event_result = params.event_result\n this.cause = params.cause\n this.timeout_seconds = params.timeout_seconds ?? this.event_result.event.event_timeout ?? null\n }\n\n get event(): BaseEvent {\n return this.event_result.event\n }\n\n get event_type(): string {\n return this.event.event_type\n }\n\n get handler_name(): string {\n return this.event_result.handler_name\n }\n\n get handler_id(): string {\n return this.event_result.handler_id\n }\n\n get event_timeout(): number | null {\n return this.event.event_timeout\n }\n}\n\n// When the handler itself timed out while executing (due to handler.handler_timeout being exceeded)\nexport class EventHandlerTimeoutError extends EventHandlerError {\n constructor(message: string, params: { event_result: EventResult; timeout_seconds?: number | null; cause?: Error }) {\n super(message, {\n event_result: params.event_result,\n timeout_seconds: params.timeout_seconds,\n cause: params.cause ?? new TimeoutError(message),\n })\n this.name = 'EventHandlerTimeoutError'\n }\n}\n\n// When a pending handler was cancelled and never run due to an error (e.g. timeout) in a parent scope\nexport class EventHandlerCancelledError extends EventHandlerError {\n constructor(message: string, params: { event_result: EventResult; timeout_seconds?: number | null; cause: Error }) {\n super(message, params)\n this.name = 'EventHandlerCancelledError'\n }\n}\n\n// When a handler that was already running was aborted due to an error in the parent scope, not due to an error in its own logic / exceeding its own timeout\nexport class EventHandlerAbortedError extends EventHandlerError {\n constructor(message: string, params: { event_result: EventResult; timeout_seconds?: number | null; cause: Error }) {\n super(message, params)\n this.name = 'EventHandlerAbortedError'\n }\n}\n\n// When a handler run successfully but returned a value that failed event_result_type validation\nexport class EventHandlerResultSchemaError extends EventHandlerError {\n raw_value: unknown\n\n constructor(message: string, params: { event_result: EventResult; timeout_seconds?: number | null; cause: Error; raw_value: unknown }) {\n super(message, params)\n this.name = 'EventHandlerResultSchemaError'\n this.raw_value = params.raw_value\n }\n\n get expected_schema(): any {\n return this.event_result.event.event_result_type\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }