{"version":3,"sources":["../src/events/pubsub.ts","../src/events/event-emitter.ts"],"names":["EventEmitter"],"mappings":"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","file":"chunk-CVF4W47C.cjs","sourcesContent":["import type { Event, EventCallback, SubscribeOptions } from './types';\n\n/**\n * Delivery model for a PubSub implementation.\n *\n * - `pull`: consumers actively read from the broker (e.g. Redis Streams\n *   XREADGROUP, GCP Pub/Sub streamingPull, SQS ReceiveMessage). Mastra runs\n *   a long-lived `OrchestrationWorker` that owns a subscription loop.\n *\n * - `push`: events arrive without the consumer asking — either in-process\n *   (EventEmitter dispatching to a registered listener) or out-of-process\n *   (the broker POSTs to an HTTP endpoint, e.g. GCP Pub/Sub push, SNS,\n *   EventBridge). Mastra wires the workflow handler directly to the pubsub\n *   for in-process push, or relies on `POST /api/workers/events` for\n *   broker push delivered over HTTP.\n */\nexport type PubSubDeliveryMode = 'pull' | 'push';\n\nexport abstract class PubSub {\n  abstract publish(topic: string, event: Omit<Event, 'id' | 'createdAt'>): Promise<void>;\n  abstract subscribe(topic: string, cb: EventCallback, options?: SubscribeOptions): Promise<void>;\n  abstract unsubscribe(topic: string, cb: EventCallback): Promise<void>;\n  abstract flush(): Promise<void>;\n\n  /**\n   * Delivery modes this PubSub implementation supports.\n   *\n   * Defaults to `['pull']` for backward compatibility — third-party\n   * implementations that don't override this property are treated as\n   * pull-mode, which preserves today's behavior.\n   *\n   * Implementations that deliver events without an active read loop (e.g.\n   * EventEmitter, GCP Pub/Sub push subscriptions) should declare `'push'`.\n   * Implementations that support both modes should declare both.\n   */\n  get supportedModes(): ReadonlyArray<PubSubDeliveryMode> {\n    return ['pull'];\n  }\n\n  /**\n   * Get historical events for a topic.\n   * Default implementation returns empty array (no history support).\n   * Override in implementations that support event caching.\n   *\n   * @param topic - The topic to get history for\n   * @param offset - Starting index (0-based), defaults to 0\n   * @returns Array of events from the specified index\n   */\n  getHistory(_topic: string, _offset?: number): Promise<Event[]> {\n    return Promise.resolve([]);\n  }\n\n  /**\n   * Subscribe to a topic with automatic replay of cached events.\n   * First replays any cached history, then subscribes to live events.\n   * Default implementation falls back to regular subscribe (no replay).\n   * Override in implementations that support event caching.\n   *\n   * @param topic - The topic to subscribe to\n   * @param cb - Callback invoked for each event (both cached and live)\n   */\n  subscribeWithReplay(topic: string, cb: EventCallback): Promise<void> {\n    return this.subscribe(topic, cb);\n  }\n\n  /**\n   * Subscribe to a topic with replay starting from a specific index.\n   * This is more efficient than full replay when the client knows their last position.\n   * Default implementation falls back to subscribeWithReplay (full replay).\n   * Override in implementations that support indexed event caching.\n   *\n   * @param topic - The topic to subscribe to\n   * @param offset - Start replaying from this index (0-based)\n   * @param cb - Callback invoked for each event\n   */\n  subscribeFromOffset(topic: string, _offset: number, cb: EventCallback): Promise<void> {\n    return this.subscribeWithReplay(topic, cb);\n  }\n}\n","import EventEmitter from 'node:events';\nimport { PubSub } from './pubsub';\nimport type { PubSubDeliveryMode } from './pubsub';\nimport type { Event, EventCallback, SubscribeOptions } from './types';\n\nexport class EventEmitterPubSub extends PubSub {\n  // EventEmitter dispatches synchronously to listeners, so it can serve both\n  // a push consumer (no worker) and a pull-style worker that simply calls\n  // `subscribe()` to register a listener. Both modes are advertised so the\n  // default in-process setup keeps using OrchestrationWorker, while\n  // genuinely push-only transports (GCP Pub/Sub push, SNS, EventBridge)\n  // declare `['push']` only and skip the worker.\n  override get supportedModes(): ReadonlyArray<PubSubDeliveryMode> {\n    return ['pull', 'push'];\n  }\n\n  private emitter: EventEmitter;\n\n  // group → topic → callbacks[]\n  private groups: Map<string, Map<string, EventCallback[]>> = new Map();\n  // \"topic:group\" → round-robin counter\n  private groupCounters: Map<string, number> = new Map();\n  // \"topic:group\" → the single listener registered on the emitter for this group\n  private groupListeners: Map<string, (event: Event) => void> = new Map();\n\n  // Track pending nack redeliveries so flush() can wait and close() can cancel them\n  private pendingNacks: Set<ReturnType<typeof setTimeout>> = new Set();\n\n  // Track delivery attempts per message id\n  private deliveryAttempts: Map<string, number> = new Map();\n\n  // topic → (original callback → wrapped listener) for fan-out (non-group) subscribers.\n  // Nested keying so the same callback registered on multiple topics keeps\n  // a distinct wrapper per topic.\n  private fanoutWrappers: Map<string, Map<EventCallback, (event: Event) => void>> = new Map();\n\n  constructor(existingEmitter?: EventEmitter) {\n    super();\n    this.emitter = existingEmitter ?? new EventEmitter();\n  }\n\n  async publish(topic: string, event: Omit<Event, 'id' | 'createdAt'>): Promise<void> {\n    const id = crypto.randomUUID();\n    const createdAt = new Date();\n    this.emitter.emit(topic, {\n      ...event,\n      id,\n      createdAt,\n      deliveryAttempt: 1,\n    });\n  }\n\n  async subscribe(topic: string, cb: EventCallback, options?: SubscribeOptions): Promise<void> {\n    if (options?.group) {\n      this.subscribeWithGroup(topic, cb, options.group);\n    } else {\n      const wrapper = (event: Event) => {\n        cb(\n          event,\n          async () => {},\n          async () => {},\n        );\n      };\n      let byCb = this.fanoutWrappers.get(topic);\n      if (!byCb) {\n        byCb = new Map();\n        this.fanoutWrappers.set(topic, byCb);\n      }\n      byCb.set(cb, wrapper);\n      this.emitter.on(topic, wrapper);\n    }\n  }\n\n  async unsubscribe(topic: string, cb: EventCallback): Promise<void> {\n    // Check if this callback is in any group for this topic\n    for (const [group, topicMap] of this.groups) {\n      const members = topicMap.get(topic);\n      if (members) {\n        const idx = members.indexOf(cb);\n        if (idx !== -1) {\n          members.splice(idx, 1);\n          // If group is now empty for this topic, remove the emitter listener\n          if (members.length === 0) {\n            topicMap.delete(topic);\n            const listenerKey = `${topic}:${group}`;\n            const listener = this.groupListeners.get(listenerKey);\n            if (listener) {\n              this.emitter.off(topic, listener);\n              this.groupListeners.delete(listenerKey);\n              this.groupCounters.delete(listenerKey);\n            }\n          }\n          if (topicMap.size === 0) {\n            this.groups.delete(group);\n          }\n          return;\n        }\n      }\n    }\n\n    // Not in a group — remove as fan-out listener\n    const byCb = this.fanoutWrappers.get(topic);\n    const wrapper = byCb?.get(cb);\n    if (wrapper && byCb) {\n      this.emitter.off(topic, wrapper);\n      byCb.delete(cb);\n      if (byCb.size === 0) this.fanoutWrappers.delete(topic);\n    } else {\n      this.emitter.off(topic, cb);\n    }\n  }\n\n  async flush(): Promise<void> {\n    // Wait for any pending nack redeliveries to fire\n    if (this.pendingNacks.size > 0) {\n      await new Promise<void>(resolve => {\n        const check = () => {\n          if (this.pendingNacks.size === 0) {\n            resolve();\n          } else {\n            setTimeout(check, 10);\n          }\n        };\n        check();\n      });\n    }\n  }\n\n  /**\n   * Clean up all listeners during graceful shutdown.\n   */\n  async close(): Promise<void> {\n    // Cancel pending nack redeliveries\n    for (const handle of this.pendingNacks) {\n      clearTimeout(handle);\n    }\n    this.pendingNacks.clear();\n    this.deliveryAttempts.clear();\n\n    this.emitter.removeAllListeners();\n    this.groups.clear();\n    this.groupCounters.clear();\n    this.groupListeners.clear();\n    this.fanoutWrappers.clear();\n  }\n\n  private subscribeWithGroup(topic: string, cb: EventCallback, group: string): void {\n    let topicMap = this.groups.get(group);\n    if (!topicMap) {\n      topicMap = new Map();\n      this.groups.set(group, topicMap);\n    }\n\n    let members = topicMap.get(topic);\n    if (!members) {\n      members = [];\n      topicMap.set(topic, members);\n    }\n\n    members.push(cb);\n\n    // Register a single emitter listener per topic:group pair\n    const listenerKey = `${topic}:${group}`;\n    if (!this.groupListeners.has(listenerKey)) {\n      const listener = (event: Event) => {\n        this.deliverToGroup(topic, group, listenerKey, event);\n      };\n\n      this.groupListeners.set(listenerKey, listener);\n      this.emitter.on(topic, listener);\n    }\n  }\n\n  private deliverToGroup(topic: string, group: string, listenerKey: string, event: Event): void {\n    const currentMembers = this.groups.get(group)?.get(topic);\n    if (!currentMembers || currentMembers.length === 0) return;\n\n    const counter = this.groupCounters.get(listenerKey) ?? 0;\n    const idx = counter % currentMembers.length;\n    this.groupCounters.set(listenerKey, counter + 1);\n\n    // Track delivery attempts scoped per group listener, so ack/nack in one\n    // group doesn't disturb another group's attempt counter for the same event.\n    const attemptKey = `${listenerKey}:${event.id}`;\n    const attempt = this.deliveryAttempts.get(attemptKey) ?? 1;\n    const eventWithAttempt = { ...event, deliveryAttempt: attempt };\n\n    const ack = async () => {\n      // Message successfully processed — clean up attempt tracking\n      this.deliveryAttempts.delete(attemptKey);\n    };\n\n    const nack = async () => {\n      // Message processing failed — redeliver to the group after a short delay\n      // Increment delivery attempt counter\n      this.deliveryAttempts.set(attemptKey, attempt + 1);\n\n      const handle = setTimeout(() => {\n        this.pendingNacks.delete(handle);\n        this.deliverToGroup(topic, group, listenerKey, event);\n      }, 0);\n      this.pendingNacks.add(handle);\n    };\n\n    currentMembers[idx]!(eventWithAttempt, ack, nack);\n  }\n}\n"]}