{"version":3,"file":"collection-subscriber.cjs","sources":["../../../../src/query/live/collection-subscriber.ts"],"sourcesContent":["import {\n  normalizeExpressionPaths,\n  normalizeOrderByPaths,\n} from '../compiler/expressions.js'\nimport {\n  computeOrderedLoadCursor,\n  computeSubscriptionOrderByHints,\n  filterDuplicateInserts,\n  sendChangesToInput,\n  splitUpdates,\n  trackBiggestSentValue,\n} from './utils.js'\nimport type { Collection } from '../../collection/index.js'\nimport type {\n  ChangeMessage,\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'\n\nconst loadMoreCallbackSymbol = Symbol.for(\n  `@tanstack/db.collection-config-builder`,\n)\n\nexport class CollectionSubscriber<\n  TContext extends Context,\n  TResult extends object = GetResult<TContext>,\n> {\n  // Keep track of the biggest value we've sent so far (needed for orderBy optimization)\n  private biggest: any = undefined\n\n  // Track the most recent ordered load request key (cursor + window).\n  // This avoids infinite loops from cached data re-writes while still allowing\n  // window moves or new keys at the same cursor value to trigger new requests.\n  private lastLoadRequestKey: string | undefined\n\n  // Track deferred promises for subscription loading states\n  private subscriptionLoadingPromises = new Map<\n    CollectionSubscription,\n    { resolve: () => void }\n  >()\n\n  // Track keys that have been sent to the D2 pipeline to prevent duplicate inserts\n  // This is necessary because different code paths (initial load, change events)\n  // can potentially send the same item to D2 multiple times.\n  private sentToD2Keys = new Set<string | number>()\n\n  // Direct load tracking callback for ordered path (set during subscribeToOrderedChanges,\n  // used by loadNextItems for subsequent requestLimitedSnapshot calls)\n  private orderedLoadSubsetResult?: (result: Promise<void> | true) => void\n  private pendingOrderedLoadPromise: Promise<void> | undefined\n\n  constructor(\n    private alias: string,\n    private collectionId: string,\n    private collection: Collection,\n    private collectionConfigBuilder: CollectionConfigBuilder<TContext, TResult>,\n  ) {}\n\n  subscribe(): CollectionSubscription {\n    const whereClause = this.getWhereClauseForAlias()\n\n    if (whereClause) {\n      const whereExpression = normalizeExpressionPaths(whereClause, this.alias)\n      return this.subscribeToChanges(whereExpression)\n    }\n\n    return this.subscribeToChanges()\n  }\n\n  private subscribeToChanges(whereExpression?: BasicExpression<boolean>) {\n    const orderByInfo = this.getOrderByInfo()\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 = (result: Promise<void> | true) => {\n      if (result instanceof Promise) {\n        this.collectionConfigBuilder.liveQueryCollection!._sync.trackLoadPromise(\n          result,\n        )\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      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\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      )\n    } else {\n      // If the source alias is lazy then we should not include the initial state\n      const includeInitialState = !this.collectionConfigBuilder.isLazyAlias(\n        this.alias,\n      )\n\n      subscription = this.subscribeToMatchingChanges(\n        whereExpression,\n        includeInitialState,\n        onStatusChange,\n      )\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 (subscription.status === `loadingSubset`) {\n      this.ensureLoadingPromise(subscription)\n    }\n\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      subscription.unsubscribe()\n    }\n    // currentSyncState is always defined when subscribe() is called\n    // (called during sync session setup)\n    this.collectionConfigBuilder.currentSyncState!.unsubscribeCallbacks.add(\n      unsubscribe,\n    )\n    return subscription\n  }\n\n  private sendChangesToPipeline(\n    changes: Iterable<ChangeMessage<any, string | number>>,\n    callback?: () => boolean,\n  ) {\n    const changesArray = Array.isArray(changes) ? changes : [...changes]\n    const filteredChanges = filterDuplicateInserts(\n      changesArray,\n      this.sentToD2Keys,\n    )\n\n    // currentSyncState and input are always defined when this method is called\n    // (only called from active subscriptions during a sync session)\n    const input =\n      this.collectionConfigBuilder.currentSyncState!.inputs[this.alias]!\n    const sentChanges = sendChangesToInput(\n      input,\n      filteredChanges,\n      this.collection.config.getKey,\n    )\n\n    // Do not provide the callback that loads more data\n    // if there's no more data to load\n    // otherwise we end up in an infinite loop trying to load more data\n    const dataLoader = sentChanges > 0 ? callback : undefined\n\n    // We need to schedule a graph run even if there's no data to load\n    // because we need to mark the collection as ready if it's not already\n    // and that's only done in `scheduleGraphRun`\n    this.collectionConfigBuilder.scheduleGraphRun(dataLoader, {\n      alias: this.alias,\n    })\n  }\n\n  private subscribeToMatchingChanges(\n    whereExpression: BasicExpression<boolean> | undefined,\n    includeInitialState: boolean,\n    onStatusChange: (event: SubscriptionStatusChangeEvent) => 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    )\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 onLoadSubsetResult = includeInitialState\n      ? (result: Promise<void> | true) => {\n          if (result instanceof Promise) {\n            this.collectionConfigBuilder.liveQueryCollection!._sync.trackLoadPromise(\n              result,\n            )\n          }\n        }\n      : undefined\n\n    const subscription = this.collection.subscribeChanges(sendChanges, {\n      ...(includeInitialState && { includeInitialState }),\n      whereExpression,\n      onStatusChange,\n      orderBy: hints.orderBy,\n      limit: hints.limit,\n      onLoadSubsetResult,\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: (result: Promise<void> | true) => void,\n  ): CollectionSubscription {\n    const { orderBy, offset, limit, index } = orderByInfo\n\n    // Store the callback so loadNextItems can also use direct tracking.\n    // Track in-flight ordered loads to avoid issuing redundant requests while\n    // a previous snapshot is still pending.\n    const handleLoadSubsetResult = (result: Promise<void> | true) => {\n      if (result instanceof Promise) {\n        this.pendingOrderedLoadPromise = result\n        result.finally(() => {\n          if (this.pendingOrderedLoadPromise === result) {\n            this.pendingOrderedLoadPromise = undefined\n          }\n        })\n      }\n      onLoadSubsetResult(result)\n    }\n\n    this.orderedLoadSubsetResult = handleLoadSubsetResult\n\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 changesArray = Array.isArray(changes) ? changes : [...changes]\n\n      this.trackSentValues(changesArray, orderByInfo.comparator)\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.sendChangesToPipelineWithTracking(\n        splittedChanges,\n        subscriptionHolder.current!,\n      )\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    })\n    subscriptionHolder.current = subscription\n\n    // Listen for truncate events to reset cursor tracking state and sentToD2Keys\n    // This ensures that after a must-refetch/truncate, we don't use stale cursor data\n    // and allow re-inserts of previously sent keys\n    const truncateUnsubscribe = this.collection.on(`truncate`, () => {\n      this.biggest = undefined\n      this.lastLoadRequestKey = undefined\n      this.pendingOrderedLoadPromise = undefined\n      this.sentToD2Keys.clear()\n    })\n\n    // Clean up truncate listener when subscription is unsubscribed\n    subscription.on(`unsubscribed`, () => {\n      truncateUnsubscribe()\n    })\n\n    // Normalize the orderBy clauses such that the references are relative to the collection\n    const normalizedOrderBy = normalizeOrderByPaths(orderBy, this.alias)\n\n    // Trigger the snapshot request — use direct load tracking (trackLoadSubsetPromise: false)\n    // to pipe the loadSubset result straight to the live query collection. This bypasses\n    // the subscription status → onStatusChange → deferred promise chain which is fragile\n    // under microtask timing (e.g., queueMicrotask delays in TanStack Query observers).\n    if (index) {\n      // We have an index on the first orderBy column - use lazy loading optimization\n      subscription.setOrderByIndex(index)\n\n      subscription.requestLimitedSnapshot({\n        limit: offset + limit,\n        orderBy: normalizedOrderBy,\n        trackLoadSubsetPromise: false,\n        onLoadSubsetResult: handleLoadSubsetResult,\n      })\n    } else {\n      // No index available (e.g., non-ref expression): pass orderBy/limit to loadSubset\n      subscription.requestSnapshot({\n        orderBy: normalizedOrderBy,\n        limit: offset + limit,\n        trackLoadSubsetPromise: false,\n        onLoadSubsetResult: handleLoadSubsetResult,\n      })\n    }\n\n    return subscription\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) {\n    const orderByInfo = this.getOrderByInfo()\n\n    if (!orderByInfo) {\n      // This query has no orderBy operator\n      // so there's no data to load\n      return true\n    }\n\n    const { dataNeeded, index } = orderByInfo\n\n    if (!dataNeeded || !index) {\n      // dataNeeded is not set when there's no index (e.g., non-ref expression\n      // or auto-indexing is disabled). Without an index, lazy loading can't work —\n      // all data was already loaded eagerly via requestSnapshot.\n      return true\n    }\n\n    if (this.pendingOrderedLoadPromise) {\n      // Wait for in-flight ordered loads to resolve before issuing another request.\n      return true\n    }\n\n    // `dataNeeded` probes the orderBy operator to see if it needs more data\n    // if it needs more data, it returns the number of items it needs\n    const n = dataNeeded()\n    if (n > 0) {\n      this.loadNextItems(n, subscription)\n    }\n    return true\n  }\n\n  private sendChangesToPipelineWithTracking(\n    changes: Iterable<ChangeMessage<any, string | number>>,\n    subscription: CollectionSubscription,\n  ) {\n    const orderByInfo = this.getOrderByInfo()\n    if (!orderByInfo) {\n      this.sendChangesToPipeline(changes)\n      return\n    }\n\n    // Cache the loadMoreIfNeeded callback on the subscription using a symbol property.\n    // This ensures we pass the same function instance to the scheduler each time,\n    // allowing it to deduplicate callbacks when multiple changes arrive during a transaction.\n    type SubscriptionWithLoader = CollectionSubscription & {\n      [loadMoreCallbackSymbol]?: () => boolean\n    }\n\n    const subscriptionWithLoader = subscription as SubscriptionWithLoader\n\n    subscriptionWithLoader[loadMoreCallbackSymbol] ??=\n      this.loadMoreIfNeeded.bind(this, subscription)\n\n    this.sendChangesToPipeline(\n      changes,\n      subscriptionWithLoader[loadMoreCallbackSymbol],\n    )\n  }\n\n  // Loads the next `n` items from the collection\n  // starting from the biggest item it has sent\n  private loadNextItems(n: number, subscription: CollectionSubscription) {\n    const orderByInfo = this.getOrderByInfo()\n    if (!orderByInfo) {\n      return\n    }\n\n    const cursor = computeOrderedLoadCursor(\n      orderByInfo,\n      this.biggest,\n      this.lastLoadRequestKey,\n      this.alias,\n      n,\n    )\n    if (!cursor) return // Duplicate request — skip\n\n    this.lastLoadRequestKey = cursor.loadRequestKey\n\n    // Take the `n` items after the biggest sent value\n    // Omit offset so requestLimitedSnapshot can advance based on\n    // the number of rows already loaded (supports offset-based backends).\n    subscription.requestLimitedSnapshot({\n      orderBy: cursor.normalizedOrderBy,\n      limit: n,\n      minValues: cursor.minValues,\n      trackLoadSubsetPromise: false,\n      onLoadSubsetResult: this.orderedLoadSubsetResult,\n    })\n  }\n\n  private getWhereClauseForAlias(): BasicExpression<boolean> | undefined {\n    const sourceWhereClausesCache =\n      this.collectionConfigBuilder.sourceWhereClausesCache\n    if (!sourceWhereClausesCache) {\n      return undefined\n    }\n    return sourceWhereClausesCache.get(this.alias)\n  }\n\n  private getOrderByInfo(): OrderByOptimizationInfo | undefined {\n    const info =\n      this.collectionConfigBuilder.optimizableOrderByCollections[\n        this.collectionId\n      ]\n    if (info && info.alias === this.alias) {\n      return info\n    }\n    return undefined\n  }\n\n  private trackSentValues(\n    changes: Array<ChangeMessage<any, string | number>>,\n    comparator: (a: any, b: any) => number,\n  ): void {\n    const result = trackBiggestSentValue(\n      changes,\n      this.biggest,\n      this.sentToD2Keys,\n      comparator,\n    )\n    this.biggest = result.biggest\n    if (result.shouldResetLoadKey) {\n      this.lastLoadRequestKey = undefined\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.liveQueryCollection!._sync.trackLoadPromise(\n      promise,\n    )\n  }\n}\n"],"names":["normalizeExpressionPaths","subscription","filterDuplicateInserts","sendChangesToInput","computeSubscriptionOrderByHints","splitUpdates","normalizeOrderByPaths","computeOrderedLoadCursor","trackBiggestSentValue"],"mappings":"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"}