{"version":3,"file":"TransactionExecutor.cjs","sources":["../../../src/executor/TransactionExecutor.ts"],"sourcesContent":["import { DuplicateTransactionIdError, createTransaction } from '@tanstack/db'\nimport { OutboxTransactionNotFoundError } from '../outbox/OutboxManager'\nimport { DefaultRetryPolicy } from '../retry/RetryPolicy'\nimport { NonRetriableError } from '../types'\nimport type { KeyScheduler } from './KeyScheduler'\nimport type { OutboxManager } from '../outbox/OutboxManager'\nimport type {\n  OfflineConfig,\n  OfflineTransaction,\n  TransactionSignaler,\n} from '../types'\n\nconst HANDLED_EXECUTION_ERROR = Symbol(`HandledExecutionError`)\n\nfunction toError(value: unknown): Error {\n  return value instanceof Error ||\n    Object.prototype.toString.call(value) === `[object Error]`\n    ? (value as Error)\n    : new Error(String(value))\n}\n\nexport class TransactionExecutor {\n  private scheduler: KeyScheduler\n  private outbox: OutboxManager\n  private config: OfflineConfig\n  private retryPolicy: DefaultRetryPolicy\n  private isExecuting = false\n  private executionPromise: Promise<void> | null = null\n  private offlineExecutor: TransactionSignaler\n  private retryTimer: ReturnType<typeof setTimeout> | null = null\n  private fatalError: Error | null = null\n\n  constructor(\n    scheduler: KeyScheduler,\n    outbox: OutboxManager,\n    config: OfflineConfig,\n    offlineExecutor: TransactionSignaler,\n  ) {\n    this.scheduler = scheduler\n    this.outbox = outbox\n    this.config = config\n    this.retryPolicy = new DefaultRetryPolicy(\n      Number.POSITIVE_INFINITY,\n      config.jitter ?? true,\n    )\n    this.offlineExecutor = offlineExecutor\n  }\n\n  async execute(transaction: OfflineTransaction): Promise<void> {\n    this.assertHealthy()\n    this.scheduler.schedule(transaction)\n    await this.executeAll()\n  }\n\n  async executeAll(): Promise<void> {\n    this.assertHealthy()\n    if (this.isExecuting) {\n      return this.executionPromise!\n    }\n\n    this.isExecuting = true\n    this.executionPromise = this.runExecution()\n\n    try {\n      await this.executionPromise\n    } finally {\n      this.isExecuting = false\n      this.executionPromise = null\n      this.scheduleNextRetry()\n    }\n  }\n\n  private async runExecution(): Promise<void> {\n    while (this.scheduler.getPendingCount() > 0) {\n      if (!this.canExecute()) {\n        break\n      }\n\n      const transaction = this.scheduler.getNext()\n\n      if (!transaction) {\n        break\n      }\n\n      await this.executeTransaction(transaction)\n    }\n  }\n\n  private async executeTransaction(\n    transaction: OfflineTransaction,\n  ): Promise<void> {\n    try {\n      const terminalError =\n        transaction.outboxPhase === `rejection-pending`\n          ? this.getTerminalError(transaction)\n          : undefined\n      this.scheduler.markStarted(transaction)\n\n      if (!transaction.outboxPhase) {\n        try {\n          await this.runMutationFn(transaction)\n        } catch (error) {\n          const err = toError(error)\n\n          await this.handleError(transaction, err)\n          ;(err as any)[HANDLED_EXECUTION_ERROR] = true\n          throw err\n        }\n      }\n\n      // A successful provider call can outlive this executor. Persist that\n      // fact before removal so a restarted executor only retries deletion.\n      const deletionPending: OfflineTransaction = transaction.outboxPhase\n        ? transaction\n        : { ...transaction, outboxPhase: `deletion-pending` }\n      try {\n        await this.removeSettledTransaction(\n          deletionPending,\n          !transaction.outboxPhase,\n        )\n      } catch (error) {\n        const storageError = error as Error\n        this.offlineExecutor.rejectTransaction(\n          transaction.id,\n          terminalError ?? storageError,\n        )\n        throw storageError\n      }\n\n      if (terminalError) {\n        this.offlineExecutor.rejectTransaction(transaction.id, terminalError)\n      } else {\n        this.offlineExecutor.resolveTransaction(transaction.id, undefined)\n      }\n    } catch (error) {\n      if (\n        error !== null &&\n        typeof error === `object` &&\n        (error as Record<symbol, unknown>)[HANDLED_EXECUTION_ERROR] === true\n      ) {\n        return\n      }\n\n      throw error\n    }\n  }\n\n  private async runMutationFn(transaction: OfflineTransaction): Promise<void> {\n    const mutationFn = this.config.mutationFns[transaction.mutationFnName]\n\n    if (!mutationFn) {\n      const errorMessage = `Unknown mutation function: ${transaction.mutationFnName}`\n\n      if (this.config.onUnknownMutationFn) {\n        this.config.onUnknownMutationFn(transaction.mutationFnName, transaction)\n      }\n\n      throw new NonRetriableError(errorMessage)\n    }\n\n    // Mutations are already PendingMutation objects with collections attached\n    // from the deserializer, so we can use them directly\n    const transactionWithMutations = {\n      id: transaction.id,\n      mutations: transaction.mutations,\n      metadata: transaction.metadata ?? {},\n    }\n\n    await mutationFn({\n      transaction: transactionWithMutations as any,\n      idempotencyKey: transaction.idempotencyKey,\n    })\n  }\n\n  private async handleError(\n    transaction: OfflineTransaction,\n    error: Error,\n  ): Promise<void> {\n    let shouldRetry: boolean\n    let hookFailure: Error | undefined\n    if (error instanceof NonRetriableError) {\n      shouldRetry = false\n    } else {\n      let decision: boolean | undefined\n      try {\n        decision = this.config.shouldRetry?.(error, transaction.retryCount)\n        if (decision !== undefined && typeof decision !== `boolean`) {\n          // An async hook is invalid, but its rejection must stay row-local.\n          void Promise.resolve(decision).catch(() => {})\n          throw new TypeError(\n            `OfflineConfig.shouldRetry must return true, false, or undefined`,\n          )\n        }\n      } catch (hookError) {\n        hookFailure = toError(hookError)\n      }\n      if (hookFailure) {\n        shouldRetry = false\n      } else {\n        shouldRetry =\n          decision ??\n          this.retryPolicy.shouldRetry(error, transaction.retryCount)\n      }\n    }\n\n    if (!shouldRetry) {\n      const terminalError = hookFailure ?? error\n      const rejectionPending: OfflineTransaction = {\n        ...transaction,\n        outboxPhase: `rejection-pending`,\n        lastError: {\n          name: terminalError.name,\n          message: terminalError.message,\n          stack: terminalError.stack,\n        },\n      }\n      if (hookFailure) {\n        console.warn(\n          `Retry decision failed for transaction ${transaction.id}:`,\n          hookFailure,\n          `Named mutation function error:`,\n          error,\n        )\n      } else {\n        console.warn(`Transaction ${transaction.id} failed permanently:`, error)\n      }\n      try {\n        await this.removeSettledTransaction(rejectionPending, true)\n      } catch (storageError) {\n        this.offlineExecutor.rejectTransaction(transaction.id, terminalError)\n        throw storageError\n      }\n\n      this.offlineExecutor.rejectTransaction(transaction.id, terminalError)\n      return\n    }\n\n    const delay = Math.max(\n      0,\n      this.retryPolicy.calculateDelay(transaction.retryCount),\n    )\n    const updatedTransaction: OfflineTransaction = {\n      ...transaction,\n      retryCount: transaction.retryCount + 1,\n      nextAttemptAt: Date.now() + delay,\n      lastError: {\n        name: error.name,\n        message: error.message,\n        stack: error.stack,\n      },\n    }\n\n    this.scheduler.updateTransaction(updatedTransaction)\n\n    try {\n      await this.outbox.update(transaction.id, updatedTransaction)\n    } catch (persistError) {\n      // Public removal can finish while the named mutation function runs.\n      // The removed row cannot be retried, but its caller still owns the\n      // provider failure and later queued work must be able to run.\n      if (persistError instanceof OutboxTransactionNotFoundError) {\n        this.scheduler.markCompleted(transaction)\n        this.offlineExecutor.rejectTransaction(transaction.id, error)\n        return\n      }\n      throw persistError\n    } finally {\n      this.scheduler.markFailed(transaction)\n    }\n  }\n\n  private async removeSettledTransaction(\n    transaction: OfflineTransaction,\n    persistMarker: boolean,\n  ): Promise<void> {\n    try {\n      if (persistMarker) {\n        try {\n          await this.outbox.update(transaction.id, transaction)\n        } catch (error) {\n          // A public removal can finish while the provider is still running.\n          if (!(error instanceof OutboxTransactionNotFoundError)) throw error\n        }\n      }\n      await this.outbox.remove(transaction.id)\n      this.scheduler.markCompleted(transaction)\n    } catch (error) {\n      const storageError = toError(error)\n      this.fatalError = storageError\n      this.scheduler.markFailed(transaction)\n      this.clearRetryTimer()\n      throw storageError\n    }\n  }\n\n  assertHealthy(): void {\n    if (this.fatalError) throw this.fatalError\n  }\n\n  private getTerminalError(transaction: OfflineTransaction): Error {\n    if (!transaction.lastError)\n      throw new Error(`Terminal transaction ${transaction.id} has no error`)\n    const { name, message, stack } = transaction.lastError\n    const error =\n      name === `NonRetriableError`\n        ? new NonRetriableError(message)\n        : new Error(message)\n    error.name = name\n    error.stack = stack\n    return error\n  }\n\n  async loadPendingTransactions(): Promise<void> {\n    let removedIds: Array<string> = []\n    await this.outbox.withAll((transactions) => {\n      const { isOfflineEnabled } = this.offlineExecutor\n      if (!isOfflineEnabled) return\n      const providerPending = transactions.filter(\n        (transaction) => !transaction.outboxPhase,\n      )\n      const selectedProvider = this.config.beforeRetry\n        ? this.config.beforeRetry(providerPending)\n        : providerPending\n      const selectedById = new Map(selectedProvider.map((tx) => [tx.id, tx]))\n      const filteredTransactions = transactions.flatMap((transaction) => {\n        if (transaction.outboxPhase) return [transaction]\n        const selected = selectedById.get(transaction.id)\n        return selected ? [selected] : []\n      })\n\n      // The retry hook is user code and may synchronously revoke replay rights.\n      if (!this.offlineExecutor.isOfflineEnabled) return\n\n      const newlyLoaded = filteredTransactions.filter((transaction) =>\n        this.scheduler.schedule(transaction),\n      )\n\n      removedIds = providerPending\n        .filter(({ id }) => !selectedById.has(id))\n        .map(({ id }) => id)\n      removedIds = this.scheduler.removePendingTransactions(removedIds)\n\n      // Restore optimistic state for loaded transactions\n      // This ensures the UI shows the optimistic data while transactions are pending\n      this.restoreOptimisticState(\n        newlyLoaded.filter(\n          (transaction) => transaction.outboxPhase !== `rejection-pending`,\n        ),\n      )\n\n      // Reset retry delays for all loaded transactions so they can run immediately\n      this.resetRetryDelays()\n\n      // Schedule retry timer for loaded transactions\n      this.scheduleNextRetry()\n    })\n\n    if (removedIds.length > 0) {\n      const error = new NonRetriableError(`Transaction excluded by beforeRetry`)\n      await Promise.all(\n        removedIds.map(async (id) => {\n          try {\n            await this.outbox.remove(id)\n            this.offlineExecutor.rejectTransaction(id, error)\n          } catch (cleanupError) {\n            console.warn(\n              `Failed to remove transaction excluded by beforeRetry:`,\n              id,\n              cleanupError,\n            )\n          }\n        }),\n      )\n    }\n  }\n\n  /**\n   * Restore optimistic state from loaded transactions.\n   * Creates internal transactions to hold the mutations so the collection's\n   * state manager can show optimistic data while waiting for sync.\n   */\n  private restoreOptimisticState(\n    transactions: Array<OfflineTransaction>,\n  ): void {\n    for (const offlineTx of transactions) {\n      if (offlineTx.mutations.length === 0) {\n        continue\n      }\n\n      try {\n        // Create a restoration transaction that holds mutations for optimistic state display.\n        // It will never commit - the real mutation is handled by the offline executor.\n        const restorationTx = createTransaction({\n          id: offlineTx.id,\n          autoCommit: false,\n          mutationFn: async () => {},\n        })\n\n        restorationTx.applyMutations(offlineTx.mutations)\n\n        // Register with each affected Collection. If one cannot track it, roll\n        // it back, so no Collection keeps a restoration nothing will settle.\n        try {\n          // The serializer resolves every mutation's Collection or throws.\n          for (const mutation of offlineTx.mutations) {\n            if (mutation.collection._state.trackTransaction(restorationTx))\n              mutation.collection._state.recomputeOptimisticState(true)\n          }\n        } catch (error) {\n          // A secondary rollback settles only this restoration; it must not\n          // roll back the user's live transactions on the same keys.\n          restorationTx.rollback({ isSecondaryRollback: true })\n          throw error\n        }\n\n        this.offlineExecutor.registerRestorationTransaction(\n          offlineTx.id,\n          restorationTx,\n        )\n      } catch (error) {\n        // A live transaction with this id already shows these mutations.\n        if (error instanceof DuplicateTransactionIdError) continue\n        console.warn(\n          `Failed to restore optimistic state for transaction ${offlineTx.id}:`,\n          error,\n        )\n      }\n    }\n  }\n\n  clear(): void {\n    this.scheduler.clear()\n    this.clearRetryTimer()\n  }\n\n  pause(): void {\n    // Retain queued work and let the issued call finish its acknowledgment.\n    this.clearRetryTimer()\n  }\n\n  getPendingCount(): number {\n    return this.scheduler.getPendingCount()\n  }\n\n  private scheduleNextRetry(): void {\n    // Clear existing timer\n    this.clearRetryTimer()\n\n    if (this.fatalError || !this.canExecute()) {\n      return\n    }\n\n    const nextRetryTime = this.getNextRetryTime()\n\n    if (nextRetryTime === null) {\n      return // No transactions pending retry\n    }\n\n    const delay = Math.max(0, nextRetryTime - Date.now())\n\n    this.retryTimer = setTimeout(() => {\n      this.executeAll().catch((error) => {\n        console.warn(`Failed to execute retry batch:`, error)\n      })\n    }, delay)\n  }\n\n  private getNextRetryTime(): number | null {\n    const allTransactions = this.scheduler.getAllPendingTransactions()\n\n    if (allTransactions.length === 0) {\n      return null\n    }\n\n    // Later transactions cannot overtake the FIFO head, even if they are ready.\n    return allTransactions[0]!.nextAttemptAt\n  }\n\n  private clearRetryTimer(): void {\n    if (this.retryTimer) {\n      clearTimeout(this.retryTimer)\n      this.retryTimer = null\n    }\n  }\n\n  private canExecute(): boolean {\n    return (\n      this.offlineExecutor.isOfflineEnabled && this.offlineExecutor.isOnline()\n    )\n  }\n\n  getRunningCount(): number {\n    return this.scheduler.getRunningCount()\n  }\n\n  resetRetryDelays(): void {\n    const allTransactions = this.scheduler.getAllPendingTransactions()\n    const updatedTransactions = allTransactions.map((transaction) => ({\n      ...transaction,\n      nextAttemptAt: Date.now(),\n    }))\n\n    this.scheduler.updateTransactions(updatedTransactions)\n  }\n}\n"],"names":["DefaultRetryPolicy","NonRetriableError","OutboxTransactionNotFoundError","createTransaction","DuplicateTransactionIdError"],"mappings":"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"}