{"version":3,"file":"collection-subscriber.cjs","sources":["../../../../src/query/live/collection-subscriber.ts"],"sourcesContent":["import { normalizeExpressionPaths } from '../compiler/expressions.js'\nimport { LoadSubsetOperationAbortedError } from '../../errors.js'\nimport { OrderedSourceLoader } from './ordered-source-loader.js'\nimport {\n  computeSubscriptionOrderByHints,\n  reconcileChangesForD2,\n  sendChangesToInput,\n  splitUpdates,\n} from './utils.js'\nimport { SubsetDemandController } from './subset-demand-controller.js'\nimport type { Collection } from '../../collection/index.js'\nimport type {\n  ChangeMessage,\n  LoadSubsetOptions,\n  LoadSubsetRequestResult,\n  SubscribeChangesOptions,\n  SubscriptionLoadSubsetErrorEvent,\n  SubscriptionStatusChangeEvent,\n} from '../../types.js'\nimport type { Context, GetResult } from '../builder/types.js'\nimport type { BasicExpression } from '../ir.js'\nimport type { OrderByOptimizationInfo } from '../compiler/order-by.js'\nimport type { CollectionConfigBuilder } from './collection-config-builder.js'\nimport type { CollectionSubscription } from '../../collection/subscription.js'\nimport type { LazyDemandPlan } from '../compiler/joins.js'\n\ntype TruncateReplayPublicationControl = NonNullable<\n  SubscribeChangesOptions[`truncateReplayPublication`]\n>\n\nexport class CollectionSubscriber<\n  TContext extends Context,\n  TResult extends object = GetResult<TContext>,\n> {\n  // Root loads in start order: a request error clears only when a load\n  // started after the failure succeeds, since a load already in flight\n  // cannot cover the data whose request failed.\n  private rootLoadsStarted = 0\n  private rootLoadsBeforeFailure = 0\n  // Track deferred promises for subscription loading states\n  private subscriptionLoadingPromises = new Map<\n    CollectionSubscription,\n    { resolve: () => void }\n  >()\n\n  // Exact row last contributed to D2 for each source key.\n  private sentToD2Rows = new Map<string | number, Record<string, unknown>>()\n\n  // Direct load tracking callback for ordered path (set during subscribeToOrderedChanges,\n  // used by loadNextItems for subsequent requestLimitedSnapshot calls)\n  private orderedLoader: OrderedSourceLoader | undefined\n  // Each needed key's failed request is a request error until a later load\n  // of the key succeeds or the query no longer needs it.\n  private readonly demand = new SubsetDemandController((planId, key, error) => {\n    const request = `${planId}:${key}`\n    if (error)\n      this.collectionConfigBuilder.reportFailedRequest(request, [error])\n    else this.collectionConfigBuilder.clearFailedRequest(request)\n  })\n\n  constructor(\n    private sourceId: string,\n    private alias: string,\n    private collection: Collection,\n    private collectionConfigBuilder: CollectionConfigBuilder<TContext, TResult>,\n  ) {}\n\n  /** The live query this subscription reads for, as `subscribers` lists it. */\n  private owner(): SubscribeChangesOptions[`owner`] {\n    return this.collectionConfigBuilder.dependent()\n  }\n\n  subscribe(): CollectionSubscription {\n    const whereClause =\n      this.collectionConfigBuilder.sourceWhereClausesCache?.get(this.sourceId)\n    return this.subscribeToChanges(\n      whereClause\n        ? normalizeExpressionPaths(whereClause, this.alias)\n        : undefined,\n    )\n  }\n\n  // A live-query Collection starts no provider work on its own: it defers\n  // acquisition until it has a subscriber or a preload.\n  private defersAcquisition(): boolean {\n    return !this.collectionConfigBuilder.hasSubscriberOrPreload()\n  }\n\n  private subscribeToChanges(whereExpression?: BasicExpression<boolean>) {\n    const orderByInfo =\n      this.collectionConfigBuilder.optimizableOrderByCollections[this.sourceId]\n\n    // Direct load promise tracking: pipes loadSubset results straight to the\n    // live query collection, avoiding the multi-hop deferred promise chain that\n    // can break under microtask timing (e.g., queueMicrotask in TanStack Query).\n    const trackLoadResult = (\n      result: LoadSubsetRequestResult,\n      options?: LoadSubsetOptions,\n    ) => {\n      // A later successful load clears this source's request error. An\n      // aborted load decides nothing, and a replay's verdict decides the\n      // loads that settle while it is judged.\n      const order = ++this.rootLoadsStarted\n      const decides = () =>\n        !options?.signal?.aborted &&\n        !(options?.subscription as CollectionSubscription | undefined)\n          ?.pendingTruncateReplacement\n      void Promise.resolve(result).then(\n        () => {\n          if (order > this.rootLoadsBeforeFailure && decides())\n            this.collectionConfigBuilder.settleRootLoad(this.sourceId)\n        },\n        () => {\n          if (decides()) this.rootLoadsBeforeFailure = this.rootLoadsStarted\n        },\n      )\n      if (result instanceof Promise) {\n        // Defer the tracked rejection by one microtask so the subscription's\n        // error event can put an initial live query in error before loading\n        // state would otherwise let it become ready.\n        const trackedResult = result.catch(async (error: unknown) => {\n          await Promise.resolve()\n          throw error\n        })\n        this.collectionConfigBuilder.trackSubsetLoadPromise(trackedResult)\n      }\n    }\n\n    // Status change handler - passed to subscribeChanges so it's registered\n    // BEFORE any snapshot is requested, preventing race conditions.\n    // Used as a fallback for status transitions not covered by direct tracking\n    // (e.g., truncate-triggered reloads that call trackLoadSubsetPromise directly).\n    const onStatusChange = (event: SubscriptionStatusChangeEvent) => {\n      if (this.collectionConfigBuilder.isLazySource(this.sourceId)) {\n        // A joined source's finished load can clear the gate that holds an\n        // ordered publication, and settling it may deliver no row. Run the\n        // graph so the held changes publish.\n        if (event.status === `ready`) {\n          this.collectionConfigBuilder.scheduleGraphRun()\n        }\n        return\n      }\n      const subscription = event.subscription as CollectionSubscription\n      if (event.status === `loadingSubset`) {\n        this.ensureLoadingPromise(subscription)\n      } else {\n        // status is 'ready'\n        const deferred = this.subscriptionLoadingPromises.get(subscription)\n        if (deferred) {\n          this.subscriptionLoadingPromises.delete(subscription)\n          deferred.resolve()\n        }\n      }\n    }\n    const onLoadSubsetError = (event: SubscriptionLoadSubsetErrorEvent) => {\n      const error = this.collectionConfigBuilder.recordSubsetError(\n        event.error,\n        // Lazy demand owns its fatal-error path. For eager sources, one\n        // successful page does not finish initial ordered refinement.\n        !this.collectionConfigBuilder.isLazySource(this.sourceId) &&\n          this.collectionConfigBuilder.liveQueryCollection?._lifecycle\n            .inFirstLoad === true,\n      )\n      // A replay in flight decides the loads it replays or that join it:\n      // their failures show in its verdict, in failure order (law 16).\n      if (\n        !this.collectionConfigBuilder.isLazySource(this.sourceId) &&\n        !(event.subscription as CollectionSubscription)\n          .pendingTruncateReplacement\n      ) {\n        this.collectionConfigBuilder.failRootLoad(this.sourceId, error)\n      }\n    }\n\n    // Create subscription with onStatusChange - listener is registered before any async work\n    let subscription: CollectionSubscription\n    if (orderByInfo) {\n      subscription = this.subscribeToOrderedChanges(\n        whereExpression,\n        orderByInfo,\n        onStatusChange,\n        trackLoadResult,\n        onLoadSubsetError,\n      )\n    } else {\n      // Lazy sources load only the subsets demanded by the compiled graph.\n      const includeInitialState =\n        (this.collection.config.syncMode !== `on-demand` ||\n          this.collectionConfigBuilder.query.limit !== 0) &&\n        !this.collectionConfigBuilder.isLazySource(this.sourceId)\n\n      subscription = this.subscribeToMatchingChanges(\n        whereExpression,\n        includeInitialState,\n        onStatusChange,\n        trackLoadResult,\n        onLoadSubsetError,\n      )\n      this.registerSubscriptionCleanup(subscription)\n    }\n\n    // Check current status after subscribing - if status is 'loadingSubset', track it.\n    // The onStatusChange listener will catch the transition to 'ready'.\n    if (\n      !this.collectionConfigBuilder.isLazySource(this.sourceId) &&\n      subscription.status === `loadingSubset`\n    ) {\n      this.ensureLoadingPromise(subscription)\n    }\n\n    return subscription\n  }\n\n  private registerSubscriptionCleanup(\n    subscription: CollectionSubscription,\n  ): void {\n    const unsubscribe = () => {\n      // If subscription has a pending promise, resolve it before unsubscribing\n      const deferred = this.subscriptionLoadingPromises.get(subscription)\n      if (deferred) {\n        this.subscriptionLoadingPromises.delete(subscription)\n        deferred.resolve()\n      }\n\n      try {\n        this.demand.clear()\n      } finally {\n        subscription.unsubscribe()\n      }\n    }\n    // currentSyncState is always defined when subscribe() is called\n    // (called during sync run setup)\n    this.collectionConfigBuilder.currentSyncState!.unsubscribeCallbacks.add(\n      unsubscribe,\n    )\n  }\n\n  setDemand(\n    subscription: CollectionSubscription,\n    plan: LazyDemandPlan,\n    keys: Set<unknown>,\n  ): void {\n    const update = this.demand.setDemand(subscription, plan, keys)\n    if (!update.changed) return\n\n    if (update.empty) {\n      this.collectionConfigBuilder.retireDemand(plan.id)\n      return\n    }\n    const generation = this.collectionConfigBuilder.beginDemand(\n      plan.id,\n      update.ready instanceof Promise,\n    )\n    const settle = () =>\n      this.collectionConfigBuilder.settleDemand(plan.id, generation)\n    if (update.ready instanceof Promise) {\n      void update.ready.then(settle, (error) =>\n        this.collectionConfigBuilder.failDemand(\n          subscription,\n          this.collection,\n          plan.id,\n          generation,\n          error,\n        ),\n      )\n    } else {\n      settle()\n    }\n  }\n\n  private sendChangesToPipeline(\n    changes: Iterable<ChangeMessage<any, string | number>>,\n  ): void {\n    const changesArray = Array.isArray(changes) ? changes : [...changes]\n    const reconciledChanges = reconcileChangesForD2(\n      changesArray,\n      this.sentToD2Rows,\n    )\n    // currentSyncState and input are always defined when this method is called\n    // (only called from active subscriptions during a sync run)\n    const input =\n      this.collectionConfigBuilder.currentSyncState!.inputs[this.sourceId]!\n    if (sendChangesToInput(input, reconciledChanges) > 0) {\n      this.collectionConfigBuilder.advanceGraphInputRevision()\n    }\n    // A zero-change source settlement can still release ordered demand.\n    this.collectionConfigBuilder.scheduleGraphRun()\n  }\n\n  private subscribeToMatchingChanges(\n    whereExpression: BasicExpression<boolean> | undefined,\n    includeInitialState: boolean,\n    onStatusChange: (event: SubscriptionStatusChangeEvent) => void,\n    onLoadSubsetResult: (\n      result: LoadSubsetRequestResult,\n      options?: LoadSubsetOptions,\n    ) => void,\n    onLoadSubsetError: (event: SubscriptionLoadSubsetErrorEvent) => void,\n  ): CollectionSubscription {\n    const sendChanges = (\n      changes: Array<ChangeMessage<any, string | number>>,\n    ) => {\n      this.sendChangesToPipeline(changes)\n    }\n\n    // Get the query's orderBy and limit to pass to loadSubset.\n    const hints = computeSubscriptionOrderByHints(\n      this.collectionConfigBuilder.query,\n      this.alias,\n      this.collectionConfigBuilder.queryCompareOptions,\n    )\n\n    // Track loading via the loadSubset promise directly.\n    // requestSnapshot uses trackLoadSubsetPromise: false (needed for truncate handling),\n    // so we use onLoadSubsetResult to get the promise and track it ourselves.\n    const subscription = this.collection.subscribeChanges(sendChanges, {\n      ...(includeInitialState && { includeInitialState }),\n      whereExpression,\n      onStatusChange,\n      onLoadSubsetError,\n      deferAcquisition: this.defersAcquisition(),\n      owner: this.owner(),\n      truncateReplayPublication: this.truncateReplayPublicationControl(),\n      orderBy: hints.orderBy,\n      limit: hints.limit,\n      onLoadSubsetResult: includeInitialState ? onLoadSubsetResult : undefined,\n    })\n\n    return subscription\n  }\n\n  private subscribeToOrderedChanges(\n    whereExpression: BasicExpression<boolean> | undefined,\n    orderByInfo: OrderByOptimizationInfo,\n    onStatusChange: (event: SubscriptionStatusChangeEvent) => void,\n    onLoadSubsetResult: (\n      result: LoadSubsetRequestResult,\n      options?: LoadSubsetOptions,\n    ) => void,\n    onLoadSubsetError: (event: SubscriptionLoadSubsetErrorEvent) => void,\n  ): CollectionSubscription {\n    // Use a holder to forward-reference subscription in the callback\n    const subscriptionHolder: { current?: CollectionSubscription } = {}\n\n    const sendChangesInRange = (\n      changes: Iterable<ChangeMessage<any, string | number>>,\n    ) => {\n      const subscription = subscriptionHolder.current\n      if (!subscription) return\n      const changesArray = Array.isArray(changes) ? changes : [...changes]\n\n      this.orderedLoader?.onSourceChanges(\n        changesArray,\n        this.sentToD2Rows,\n        (key) => this.collection._hasOptimisticOverlay(key),\n      )\n\n      // Split live updates into a delete of the old value and an insert of the new value\n      const splittedChanges = splitUpdates(changesArray)\n      this.sendChangesToPipeline(splittedChanges)\n    }\n\n    // Subscribe to changes with onStatusChange - listener is registered before any snapshot\n    // values bigger than what we've sent don't need to be sent because they can't affect the topK\n    const subscription = this.collection.subscribeChanges(sendChangesInRange, {\n      whereExpression,\n      onStatusChange,\n      onLoadSubsetError,\n      deferAcquisition: this.defersAcquisition(),\n      owner: this.owner(),\n      truncateReplayPublication: this.truncateReplayPublicationControl(\n        (retired) => {\n          // Recovery favors a simple, authoritative rebuild over resuming a\n          // fragile cursor. The retained full-source demand is replayed on later\n          // truncates, so this adds at most one demand per subscription.\n          // Queue startup inside the publication barrier too: a synchronous\n          // throw establishes no acquisition for the replay to wait on.\n          // A truncate resets the cursor below; a reload's replay has no\n          // truncate, and the retired run's ordered loads are obsolete.\n          const loader = this.orderedLoader\n          if (retired) loader?.resetCursor()\n          // A window move in flight follows the replay that replaces its\n          // loads: it fails when the replay fails, without advancing the\n          // window (Atomic window publication, law 16). An aborted replay\n          // decides nothing: the replay that replaced it joins the move too.\n          const replay = subscriptionHolder.current?.pendingTruncateReplacement\n          if (replay) {\n            const decided = replay.catch((error: unknown) => {\n              if (!(error instanceof LoadSubsetOperationAbortedError))\n                throw error\n            })\n            // With no move in flight, nothing waits for the verdict.\n            void decided.catch(() => undefined)\n            this.collectionConfigBuilder.trackSubsetLoadOperationPromise(\n              decided,\n            )\n          }\n          this.collectionConfigBuilder.trackOrderedLoadPromise(\n            Promise.resolve().then(() => loader?.loadFullSource()),\n            true,\n          )\n        },\n      ),\n    })\n    subscriptionHolder.current = subscription\n    this.registerSubscriptionCleanup(subscription)\n\n    // Reset ordered-load state on truncate. Keep exact D2 rows until the\n    // replacement publication retracts or replaces them.\n    const truncateUnsubscribe = this.collection.on(`truncate`, () => {\n      this.orderedLoader?.resetCursor()\n    })\n\n    // The sync adapter reports that served pages may have shifted after its\n    // own refetch. Re-establish the window with a bounded repair.\n    const revalidationUnsubscribe = this.collection.on(\n      `loadedSubsets:invalidated`,\n      () => {\n        const loader = this.orderedLoader\n        if (!loader) return\n        loader.revalidateLoadedCoverage()\n        this.collectionConfigBuilder.scheduleGraphRunIfSyncRunCurrent(\n          this.collectionConfigBuilder.getSyncRunGeneration(),\n        )\n      },\n    )\n\n    // Clean up truncate listener when subscription is unsubscribed\n    subscription.on(`unsubscribed`, () => {\n      truncateUnsubscribe()\n      revalidationUnsubscribe()\n      subscriptionHolder.current = undefined\n      this.orderedLoader?.dispose()\n      this.orderedLoader = undefined\n    })\n\n    this.orderedLoader = new OrderedSourceLoader(\n      orderByInfo,\n      subscription,\n      this.alias,\n      (result, holdPublication, settlesAsync, options) => {\n        if (result instanceof Promise) {\n          this.collectionConfigBuilder.trackOrderedLoadPromise(\n            result,\n            holdPublication &&\n              settlesAsync &&\n              !subscription.hasPendingTruncateReplacement,\n          )\n        }\n        onLoadSubsetResult(result, options)\n      },\n      () =>\n        this.collectionConfigBuilder.liveQueryCollection?.status === `ready` &&\n        !this.collectionConfigBuilder.hasActiveWindowOperation(),\n      () => this.collectionConfigBuilder.getGraphInputRevision(),\n      () =>\n        orderByInfo.joinedFilterSourceId !== undefined &&\n        this.collectionConfigBuilder.hasPendingJoinedWork(\n          orderByInfo.joinedFilterSourceId,\n        ),\n    )\n    this.orderedLoader.start()\n\n    return subscription\n  }\n\n  private truncateReplayPublicationControl(\n    onStart?: (retired: boolean) => void,\n  ): TruncateReplayPublicationControl {\n    const syncRunGeneration =\n      this.collectionConfigBuilder.getSyncRunGeneration()\n    const isCurrent = () =>\n      syncRunGeneration === this.collectionConfigBuilder.getSyncRunGeneration()\n    // The replay's verdict decides every request error of the demand it\n    // replayed: its success clears them, and its failure replaces them with\n    // its own failures. The query then keeps its last snapshot, which no\n    // longer updates: a request error, or a failed first load before\n    // readiness. Its failures count before the request errors it replaces\n    // leave, so a failure it lists again keeps its place and its `at` (law\n    // 17). Each request error it changes is still announced on its own (see\n    // the coverage map).\n    const decide = (errors: Array<Error> = []) => {\n      if (errors.length > 0)\n        this.collectionConfigBuilder.failReplay(this.sourceId, errors)\n      else this.collectionConfigBuilder.settleReplayedRequests(this.sourceId)\n      this.collectionConfigBuilder.settleRootLoad(this.sourceId)\n      this.demand.clearRequestErrors()\n    }\n    return {\n      start: (retired) => onStart?.(retired),\n      siblingReplays: () =>\n        this.collectionConfigBuilder.siblingReplays(\n          this.collection,\n          this.sourceId,\n        ),\n      succeed: () => {\n        if (!isCurrent()) return\n        this.orderedLoader?.settleFullSourceReplay()\n        decide()\n        this.collectionConfigBuilder.scheduleGraphRunIfSyncRunCurrent(\n          syncRunGeneration,\n        )\n      },\n      fail: (errors) => {\n        if (isCurrent()) decide(errors)\n      },\n    }\n  }\n\n  // This function is called by maybeRunGraph\n  // after each iteration of the query pipeline\n  // to ensure that the orderBy operator has enough data to work with\n  loadMoreIfNeeded(subscription: CollectionSubscription): void {\n    if (\n      subscription.hasPendingTruncateReplacement &&\n      !this.collectionConfigBuilder.hasActiveWindowOperation()\n    ) {\n      return\n    }\n\n    const orderByInfo =\n      this.collectionConfigBuilder.optimizableOrderByCollections[this.sourceId]\n\n    if (!orderByInfo) {\n      // This query has no orderBy operator\n      // so there's no data to load\n      return\n    }\n\n    try {\n      const pending = this.orderedLoader?.loadMore(\n        this.collectionConfigBuilder.getActiveWindowOperationGeneration(),\n      )\n      if (pending) {\n        this.collectionConfigBuilder.trackSubsetLoadOperationPromise(pending)\n      }\n    } catch (error) {\n      if (!Object.is(subscription.lastError, error)) throw error\n    }\n  }\n\n  private ensureLoadingPromise(subscription: CollectionSubscription) {\n    if (this.subscriptionLoadingPromises.has(subscription)) {\n      return\n    }\n\n    let resolve: () => void\n    const promise = new Promise<void>((res) => {\n      resolve = res\n    })\n\n    this.subscriptionLoadingPromises.set(subscription, {\n      resolve: resolve!,\n    })\n    this.collectionConfigBuilder.trackSubsetLoadPromise(promise)\n  }\n}\n"],"names":["collectionConfigBuilder","rootLoadsStarted","rootLoadsBeforeFailure","subscriptionLoadingPromises","sentToD2Rows","SubsetDemandController","subscribeToChanges","normalizeExpressionPaths","defersAcquisition","subscription","ensureLoadingPromise","subscribeToOrderedChanges","subscribeToMatchingChanges","registerSubscriptionCleanup","sendChangesToPipeline","reconcileChangesForD2","sendChangesToInput","computeSubscriptionOrderByHints","truncateReplayPublicationControl","orderedLoader","splitUpdates","LoadSubsetOperationAbortedError","OrderedSourceLoader","errors"],"mappings":"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"}