@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 34.2 kB
Source Map (JSON)
{"version":3,"file":"live-query-window-controller.cjs","sources":["../../src/live-query-window-controller.ts"],"sourcesContent":["import {\n LiveQueryWindowControllerDisposedError,\n SetWindowRequiresOrderByError,\n} from './errors.js'\nimport { getLiveQueryStatusFlags } from './live-query-adapter.js'\nimport { createLiveQueryObserver } from './live-query-observer.js'\nimport type {\n LiveQueryObserver,\n LiveQuerySnapshot,\n} from './live-query-observer.js'\nimport type { Collection } from './collection/index.js'\nimport type { CollectionStatus } from './types.js'\n\nconst DEFAULT_PAGE_SIZE = 20\n\ntype WindowResult = true | Promise<void>\n\ntype WindowTarget = object & {\n utils?: {\n setWindow?: (options: { offset: number; limit: number }) => WindowResult\n getWindow?: () => { offset: number; limit: number } | undefined\n }\n}\n\ntype PendingWindow = {\n generation: number\n limit: number\n promise: Promise<void>\n}\n\nclass WindowCoordinator {\n private readonly leases = new Map<symbol, number>()\n private readonly leaseVersions = new Map<symbol, number>()\n private readonly initialWindow: { offset: number; limit: number } | undefined\n private appliedLimit: number | undefined\n private pending: PendingWindow | undefined\n private generation = 0\n private leaseVersion = 0\n\n constructor(private readonly target: WindowTarget) {\n this.initialWindow = target.utils?.getWindow?.()\n }\n\n request(lease: symbol, limit: number): WindowResult {\n const previousLimit = this.leases.get(lease)\n const previousVersion = this.leaseVersions.get(lease)\n const version = ++this.leaseVersion\n this.leases.set(lease, limit)\n this.leaseVersions.set(lease, version)\n\n let result: WindowResult\n try {\n result = this.applyDesiredWindow()\n } catch (error) {\n this.rollbackLease(lease, version, previousLimit, previousVersion)\n this.appliedLimit = undefined\n throw error\n }\n\n if (result === true) return true\n return result.catch(async (error: unknown) => {\n if (this.rollbackLease(lease, version, previousLimit, previousVersion)) {\n this.generation++\n this.pending = undefined\n this.appliedLimit = undefined\n try {\n if (this.leases.size === 0) {\n this.restoreInitialWindow()\n } else {\n const rollback = this.applyDesiredWindow()\n if (rollback !== true) await rollback\n }\n } catch {\n // Preserve the failure from the requested window.\n }\n }\n throw error\n })\n }\n\n isLeaseSatisfied(lease: symbol, minimumLimit: number): boolean {\n const limit = this.leases.get(lease)\n if (limit === undefined || limit < minimumLimit) return false\n const desiredLimit = this.getDesiredLimit()\n const currentWindow = this.target.utils?.getWindow?.()\n return (\n currentWindow === undefined ||\n (currentWindow.offset === 0 && currentWindow.limit === desiredLimit)\n )\n }\n\n release(lease: symbol): void {\n if (!this.leases.delete(lease)) return\n this.leaseVersions.delete(lease)\n\n // A pending request may still mutate the physical operator, but it no longer\n // establishes the accepted window for the remaining lease set.\n this.generation++\n this.pending = undefined\n this.appliedLimit = undefined\n\n if (this.leases.size === 0) {\n return\n }\n\n try {\n const result = this.applyDesiredWindow()\n if (result !== true) {\n void result.catch(() => {\n // Unsubscribe has no async error channel. Leave the physical window\n // unaccepted so the next request retries it.\n this.appliedLimit = undefined\n })\n }\n } catch {\n // The remaining controller will retry on its next request.\n this.appliedLimit = undefined\n }\n }\n\n private getDesiredLimit(): number | undefined {\n let desired: number | undefined\n for (const limit of this.leases.values()) {\n desired = desired === undefined ? limit : Math.max(desired, limit)\n }\n return desired\n }\n\n private rollbackLease(\n lease: symbol,\n version: number,\n previousLimit: number | undefined,\n previousVersion: number | undefined,\n ): boolean {\n if (this.leaseVersions.get(lease) !== version) return false\n if (previousLimit === undefined) {\n this.leases.delete(lease)\n this.leaseVersions.delete(lease)\n } else {\n this.leases.set(lease, previousLimit)\n if (previousVersion === undefined) {\n this.leaseVersions.delete(lease)\n } else {\n this.leaseVersions.set(lease, previousVersion)\n }\n }\n return true\n }\n\n private restoreInitialWindow(): void {\n const setWindow = this.target.utils?.setWindow\n if (!this.initialWindow || typeof setWindow !== `function`) return\n try {\n const result = setWindow.call(this.target.utils, this.initialWindow)\n if (result !== true) void result.catch(() => {})\n } catch {\n // Release has no error channel. A future lease will retry its own window.\n }\n }\n\n private applyDesiredWindow(): WindowResult {\n const limit = this.getDesiredLimit()\n if (limit === undefined) return true\n if (this.pending?.limit === limit) return this.pending.promise\n if (this.pending) {\n // `setWindow` mutates the physical operator before its load promise\n // settles. A different desired window must therefore be applied again,\n // even when it matches the last settled limit.\n this.generation++\n this.pending = undefined\n this.appliedLimit = undefined\n }\n const currentWindow = this.target.utils?.getWindow?.()\n if (\n limit === this.appliedLimit &&\n currentWindow?.offset === 0 &&\n currentWindow.limit === limit\n ) {\n return true\n }\n\n const setWindow = this.target.utils?.setWindow\n if (typeof setWindow !== `function`) {\n throw new SetWindowRequiresOrderByError()\n }\n\n const generation = ++this.generation\n const result = setWindow.call(this.target.utils, { offset: 0, limit })\n if (result === true) {\n if (generation === this.generation && this.getDesiredLimit() === limit) {\n this.appliedLimit = limit\n }\n return true\n }\n\n const promise = result.then(\n () => {\n if (\n generation === this.generation &&\n this.getDesiredLimit() === limit\n ) {\n this.appliedLimit = limit\n }\n if (this.pending?.generation === generation) {\n this.pending = undefined\n }\n },\n (error: unknown) => {\n if (this.pending?.generation === generation) {\n this.pending = undefined\n }\n throw error\n },\n )\n this.pending = { generation, limit, promise }\n return promise\n }\n}\n\nconst windowCoordinators = new WeakMap<object, WindowCoordinator>()\n\nfunction getWindowCoordinator(target: WindowTarget): WindowCoordinator {\n let coordinator = windowCoordinators.get(target)\n if (!coordinator) {\n coordinator = new WindowCoordinator(target)\n windowCoordinators.set(target, coordinator)\n }\n return coordinator\n}\n\n/**\n * A page-windowed view of a live query at a point in time.\n *\n * @internal This contract is unstable while RFC #1623 is being implemented.\n */\nexport interface LiveQueryWindowSnapshot<\n T extends object,\n TKey extends string | number,\n> {\n /** Rows across all committed pages, with the peek-ahead row removed. */\n data: ReadonlyArray<T>\n /** Rows grouped into committed pages of `pageSize`. */\n pages: ReadonlyArray<ReadonlyArray<T>>\n /** `initialPageParam + i` for each committed page. */\n pageParams: ReadonlyArray<number>\n hasNextPage: boolean\n isFetchingNextPage: boolean\n /** The last pagination failure, cleared when a retry begins. */\n error: unknown\n /** Keyed results for the physical window, or `undefined` when disabled. */\n state: ReadonlyMap<TKey, T> | undefined\n collection: Collection<T, TKey, any> | undefined\n status: CollectionStatus | `disabled`\n isLoading: boolean\n isReady: boolean\n isIdle: boolean\n isError: boolean\n isCleanedUp: boolean\n isEnabled: boolean\n}\n\n/** @internal This contract is unstable while RFC #1623 is being implemented. */\nexport interface CreateLiveQueryWindowControllerOptions {\n /** Rows per page (default 20). Non-positive values use the default. */\n pageSize?: number\n /** Value of the first page's `pageParam` (default 0). */\n initialPageParam?: number\n /** Committed pages to preserve when a framework binding changes page shape. */\n initialPageCount?: number\n}\n\n/** @internal This contract is unstable while RFC #1623 is being implemented. */\nexport interface LiveQueryWindowController<\n T extends object,\n TKey extends string | number,\n> {\n getSnapshot: () => LiveQueryWindowSnapshot<T, TKey>\n subscribe: (listener: () => void) => () => void\n /** Load one more page, resolving only after that page is committed. */\n fetchNextPage: () => Promise<void>\n /** Reset to the first page, resolving after the smaller window is accepted. */\n reset: () => Promise<void>\n preload: () => Promise<void>\n dispose: () => void\n}\n\ninterface CachedFrom {\n observerSnapshot: unknown\n committedPageCount: number\n isFetchingNextPage: boolean\n hasPaginationError: boolean\n paginationError: unknown\n failedHasNextPage: boolean\n}\n\ninterface SubscriptionRecord {\n listener: () => void\n active: boolean\n}\n\ninterface Publication {\n targets: Array<SubscriptionRecord>\n}\n\nclass LiveQueryWindowControllerImpl<\n T extends object,\n TKey extends string | number,\n> implements LiveQueryWindowController<T, TKey> {\n private readonly observer: LiveQueryObserver<T, TKey>\n private readonly collection: Collection<T, TKey, any> | null\n private readonly coordinator: WindowCoordinator | null\n private readonly lease = Symbol(`liveQueryWindowLease`)\n private readonly pageSize: number\n private readonly initialPageParam: number\n\n private committedPageCount: number\n private isFetchingNextPage = false\n private hasPaginationError = false\n private paginationError: unknown\n private failedHasNextPage = false\n private windowGeneration = 0\n private pendingWindowGeneration: number | undefined\n private leaseActive = false\n private leaseGeneration = 0\n private inFlightLeaseHolders = 0\n\n private readonly subscriptions = new Set<SubscriptionRecord>()\n private readonly publicationQueue: Array<Publication> = []\n private dispatching = false\n private blockDelivery = false\n private transitionDepth = 0\n private transitionNeedsNotify = false\n private observerUnsub: (() => void) | null = null\n private cachedSnapshot: LiveQueryWindowSnapshot<T, TKey> | null = null\n private cachedFrom: CachedFrom | null = null\n private disposed = false\n\n constructor(\n collection: Collection<T, TKey, any> | null,\n options: CreateLiveQueryWindowControllerOptions,\n ) {\n this.collection = collection\n this.coordinator = collection\n ? getWindowCoordinator(collection as unknown as WindowTarget)\n : null\n this.pageSize =\n options.pageSize !== undefined && options.pageSize > 0\n ? options.pageSize\n : DEFAULT_PAGE_SIZE\n this.initialPageParam = options.initialPageParam ?? 0\n const initialPageCount = Math.floor(options.initialPageCount ?? 1)\n this.committedPageCount = Number.isFinite(initialPageCount)\n ? Math.max(1, initialPageCount)\n : 1\n // The controller listener carries no delta payload, so wholesale is the\n // only coherent observer contract and guarantees non-reentrant subscribe.\n this.observer = createLiveQueryObserver<T, TKey>(collection, {\n mode: `wholesale`,\n })\n }\n\n getSnapshot(): LiveQueryWindowSnapshot<T, TKey> {\n const observerSnapshot = this.observer.getSnapshot()\n const cached = this.cachedSnapshot\n if (\n cached &&\n this.cachedFrom &&\n this.cachedFrom.observerSnapshot === observerSnapshot &&\n this.cachedFrom.committedPageCount === this.committedPageCount &&\n this.cachedFrom.isFetchingNextPage === this.isFetchingNextPage &&\n this.cachedFrom.hasPaginationError === this.hasPaginationError &&\n this.cachedFrom.paginationError === this.paginationError &&\n this.cachedFrom.failedHasNextPage === this.failedHasNextPage\n ) {\n return cached\n }\n\n const enabled = observerSnapshot.isEnabled\n const rows =\n enabled && Array.isArray(observerSnapshot.data)\n ? (observerSnapshot.data as ReadonlyArray<T>)\n : []\n const totalRequested = this.committedPageCount * this.pageSize\n const computedHasNextPage = enabled && rows.length > totalRequested\n const hasNextPage = this.hasPaginationError\n ? this.failedHasNextPage\n : computedHasNextPage\n\n const pageCount = enabled ? this.committedPageCount : 0\n const pages: Array<ReadonlyArray<T>> = []\n const pageParams: Array<number> = []\n for (let i = 0; i < pageCount; i++) {\n pages.push(rows.slice(i * this.pageSize, (i + 1) * this.pageSize))\n pageParams.push(this.initialPageParam + i)\n }\n\n const status = this.hasPaginationError ? `error` : observerSnapshot.status\n const statusFlags = this.hasPaginationError\n ? getLiveQueryStatusFlags(`error`)\n : observerSnapshot\n this.cachedSnapshot = {\n data: rows.slice(0, totalRequested),\n pages,\n pageParams,\n hasNextPage,\n isFetchingNextPage: this.isFetchingNextPage,\n error: this.hasPaginationError ? this.paginationError : undefined,\n state: observerSnapshot.state,\n collection: observerSnapshot.collection,\n status,\n isLoading: statusFlags.isLoading,\n isReady: statusFlags.isReady,\n isIdle: statusFlags.isIdle,\n isError: statusFlags.isError,\n isCleanedUp: observerSnapshot.isCleanedUp,\n isEnabled: observerSnapshot.isEnabled,\n }\n this.cachedFrom = {\n observerSnapshot,\n committedPageCount: this.committedPageCount,\n isFetchingNextPage: this.isFetchingNextPage,\n hasPaginationError: this.hasPaginationError,\n paginationError: this.paginationError,\n failedHasNextPage: this.failedHasNextPage,\n }\n return this.cachedSnapshot\n }\n\n subscribe(listener: () => void): () => void {\n if (this.disposed) throw new LiveQueryWindowControllerDisposedError()\n\n const record: SubscriptionRecord = { listener, active: true }\n this.subscriptions.add(record)\n if (this.subscriptions.size === 1) {\n this.blockDelivery = true\n let observerUnsub: (() => void) | null = null\n try {\n // Store the desired physical window before observer activation can\n // compile or restart the live-query pipeline.\n const windowResult = this.ensureLeaseActive(this.committedPageCount)\n const leaseGeneration = this.leaseGeneration\n observerUnsub = this.observer.subscribe(() => this.onObserverNotify())\n this.observerUnsub = observerUnsub\n if (windowResult !== true) {\n this.trackAttachmentFailure(windowResult, leaseGeneration)\n }\n } catch (error) {\n observerUnsub?.()\n this.observerUnsub = null\n this.deactivateLease()\n record.active = false\n this.subscriptions.delete(record)\n throw error\n } finally {\n this.blockDelivery = false\n }\n }\n\n return () => {\n if (!record.active) return\n record.active = false\n this.subscriptions.delete(record)\n if (this.subscriptions.size === 0) {\n this.observerUnsub?.()\n this.observerUnsub = null\n if (this.inFlightLeaseHolders === 0) this.deactivateLease()\n }\n }\n }\n\n fetchNextPage(): Promise<void> {\n if (this.disposed || this.isFetchingNextPage) return Promise.resolve()\n if (!this.getSnapshot().hasNextPage) return Promise.resolve()\n return this.requestPageCount(this.committedPageCount + 1, true)\n }\n\n reset(): Promise<void> {\n if (this.disposed) return Promise.resolve()\n if (\n this.committedPageCount === 1 &&\n !this.hasPaginationError &&\n !this.isFetchingNextPage &&\n this.pendingWindowGeneration === undefined\n ) {\n return Promise.resolve()\n }\n return this.requestPageCount(1, false)\n }\n\n async preload(): Promise<void> {\n if (this.disposed) throw new LiveQueryWindowControllerDisposedError()\n\n const hadPaginationError = this.hasPaginationError\n this.hasPaginationError = false\n this.paginationError = undefined\n this.acquireInFlightLease()\n try {\n const result = this.ensureLeaseActive(this.committedPageCount)\n if (result !== true) await result\n await this.observer.preload()\n this.failedHasNextPage = false\n if (hadPaginationError) this.notify()\n } catch (error) {\n this.hasPaginationError = true\n this.paginationError = error\n this.failedHasNextPage = this.getComputedHasNextPage()\n this.notify()\n throw error\n } finally {\n this.releaseInFlightLease()\n }\n }\n\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n this.windowGeneration++\n this.pendingWindowGeneration = undefined\n this.observerUnsub?.()\n this.observerUnsub = null\n this.deactivateLease()\n this.observer.dispose()\n for (const record of this.subscriptions) record.active = false\n this.subscriptions.clear()\n this.publicationQueue.length = 0\n }\n\n private requestPageCount(\n requestedPageCount: number,\n fetchingNextPage: boolean,\n ): Promise<void> {\n const generation = ++this.windowGeneration\n const previousHasNextPage = this.getSnapshot().hasNextPage\n this.pendingWindowGeneration = undefined\n this.acquireInFlightLease()\n\n this.beginTransition()\n this.isFetchingNextPage = fetchingNextPage\n this.hasPaginationError = false\n this.paginationError = undefined\n if (fetchingNextPage) this.notify()\n\n let result: WindowResult\n try {\n result = this.activateLease(requestedPageCount)\n } catch (error) {\n this.isFetchingNextPage = false\n this.hasPaginationError = true\n this.paginationError = error\n this.failedHasNextPage = previousHasNextPage\n this.notify()\n this.endTransition()\n this.releaseInFlightLease()\n return Promise.reject(error)\n }\n\n if (result === true) {\n if (!this.disposed && generation === this.windowGeneration) {\n this.committedPageCount = requestedPageCount\n this.isFetchingNextPage = false\n this.failedHasNextPage = false\n this.notify()\n }\n this.endTransition()\n this.releaseInFlightLease()\n return Promise.resolve()\n }\n\n this.pendingWindowGeneration = generation\n this.endTransition()\n\n return result\n .then(\n () => {\n if (this.disposed || generation !== this.windowGeneration) return\n this.beginTransition()\n this.pendingWindowGeneration = undefined\n this.committedPageCount = requestedPageCount\n this.isFetchingNextPage = false\n this.failedHasNextPage = false\n this.notify()\n this.endTransition()\n },\n (error: unknown) => {\n if (!this.disposed && generation === this.windowGeneration) {\n this.beginTransition()\n this.pendingWindowGeneration = undefined\n this.isFetchingNextPage = false\n this.hasPaginationError = true\n this.paginationError = error\n this.failedHasNextPage = previousHasNextPage\n this.notify()\n this.endTransition()\n }\n throw error\n },\n )\n .finally(() => {\n this.releaseInFlightLease()\n })\n }\n\n private acquireInFlightLease(): void {\n this.inFlightLeaseHolders++\n }\n\n private releaseInFlightLease(): void {\n this.inFlightLeaseHolders--\n if (this.inFlightLeaseHolders === 0 && this.subscriptions.size === 0) {\n this.deactivateLease()\n }\n }\n\n private activateLease(pageCount: number): WindowResult {\n this.leaseGeneration++\n if (!this.coordinator || !this.collection) return true\n this.leaseActive = true\n return this.coordinator.request(this.lease, pageCount * this.pageSize + 1)\n }\n\n private ensureLeaseActive(pageCount: number): WindowResult {\n const minimumLimit = pageCount * this.pageSize + 1\n if (\n this.leaseActive &&\n this.coordinator?.isLeaseSatisfied(this.lease, minimumLimit)\n ) {\n return true\n }\n return this.activateLease(pageCount)\n }\n\n private deactivateLease(): void {\n if (!this.leaseActive || !this.coordinator) return\n this.leaseGeneration++\n this.leaseActive = false\n this.coordinator.release(this.lease)\n }\n\n private trackAttachmentFailure(\n result: Promise<void>,\n leaseGeneration: number,\n ): void {\n void result.catch((error: unknown) => {\n if (\n this.disposed ||\n !this.leaseActive ||\n leaseGeneration !== this.leaseGeneration\n ) {\n return\n }\n this.beginTransition()\n this.hasPaginationError = true\n this.paginationError = error\n this.failedHasNextPage = this.getComputedHasNextPage()\n this.notify()\n this.endTransition()\n })\n }\n\n private getComputedHasNextPage(): boolean {\n const snapshot: LiveQuerySnapshot<T, TKey> = this.observer.getSnapshot()\n return (\n snapshot.isEnabled &&\n Array.isArray(snapshot.data) &&\n snapshot.data.length > this.committedPageCount * this.pageSize\n )\n }\n\n private onObserverNotify(): void {\n this.notify()\n }\n\n private beginTransition(): void {\n this.transitionDepth++\n }\n\n private endTransition(): void {\n this.transitionDepth--\n if (this.transitionDepth === 0 && this.transitionNeedsNotify) {\n this.transitionNeedsNotify = false\n this.publish()\n }\n }\n\n private notify(): void {\n if (this.transitionDepth > 0) {\n this.transitionNeedsNotify = true\n return\n }\n this.publish()\n }\n\n private publish(): void {\n if (this.disposed || this.blockDelivery || this.subscriptions.size === 0) {\n return\n }\n\n this.publicationQueue.push({ targets: [...this.subscriptions] })\n if (this.dispatching) return\n\n this.dispatching = true\n try {\n while (this.publicationQueue.length > 0) {\n const publication = this.publicationQueue.shift()!\n for (const record of publication.targets) {\n if (this.hasBeenDisposed()) return\n if (!record.active) continue\n record.listener()\n }\n }\n } finally {\n this.dispatching = false\n }\n }\n\n private hasBeenDisposed(): boolean {\n return this.disposed\n }\n}\n\n/**\n * Create an internal forward-window controller for an ordered live query.\n *\n * @internal This factory is unstable while RFC #1623 is being implemented.\n */\nexport function createLiveQueryWindowController<\n T extends object,\n TKey extends string | number,\n>(\n collection: Collection<T, TKey, any> | null | undefined,\n options: CreateLiveQueryWindowControllerOptions = {},\n): LiveQueryWindowController<T, TKey> {\n return new LiveQueryWindowControllerImpl<T, TKey>(collection ?? null, options)\n}\n"],"names":["SetWindowRequiresOrderByError","createLiveQueryObserver","getLiveQueryStatusFlags","LiveQueryWindowControllerDisposedError"],"mappings":"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"}