|
6 | 6 | } from "@electric-sql/client" |
7 | 7 | import { Store } from "@tanstack/store" |
8 | 8 | import DebugModule from "debug" |
| 9 | +import { DeduplicatedLoadSubset } from "@tanstack/db" |
9 | 10 | import { |
10 | 11 | ExpectedNumberInAwaitTxIdError, |
11 | 12 | StreamAbortedError, |
@@ -716,6 +717,21 @@ function createElectricSync<T extends Row<unknown>>( |
716 | 717 | const newSnapshots: Array<PostgresSnapshot> = [] |
717 | 718 | let hasReceivedUpToDate = false // Track if we've completed initial sync in progressive mode |
718 | 719 |
|
| 720 | + // Create deduplicated loadSubset wrapper for non-eager modes |
| 721 | + // This prevents redundant snapshot requests when multiple concurrent |
| 722 | + // live queries request overlapping or subset predicates |
| 723 | + const loadSubsetDedupe = |
| 724 | + syncMode === `eager` |
| 725 | + ? null |
| 726 | + : new DeduplicatedLoadSubset(async (opts: LoadSubsetOptions) => { |
| 727 | + // In progressive mode, stop requesting snapshots once full sync is complete |
| 728 | + if (syncMode === `progressive` && hasReceivedUpToDate) { |
| 729 | + return |
| 730 | + } |
| 731 | + const snapshotParams = compileSQL<T>(opts) |
| 732 | + await stream.requestSnapshot(snapshotParams) |
| 733 | + }) |
| 734 | + |
719 | 735 | unsubscribeStream = stream.subscribe((messages: Array<Message<T>>) => { |
720 | 736 | let hasUpToDate = false |
721 | 737 | let hasSnapshotEnd = false |
@@ -799,6 +815,10 @@ function createElectricSync<T extends Row<unknown>>( |
799 | 815 |
|
800 | 816 | truncate() |
801 | 817 |
|
| 818 | + // Reset the loadSubset deduplication state since we're starting fresh |
| 819 | + // This ensures that previously loaded predicates don't prevent refetching after truncate |
| 820 | + loadSubsetDedupe?.reset() |
| 821 | + |
802 | 822 | // Reset flags so we continue accumulating changes until next up-to-date |
803 | 823 | hasUpToDate = false |
804 | 824 | hasSnapshotEnd = false |
@@ -858,23 +878,10 @@ function createElectricSync<T extends Row<unknown>>( |
858 | 878 | } |
859 | 879 | }) |
860 | 880 |
|
861 | | - // Only set onLoadSubset if the sync mode is not eager, this indicates to the sync |
862 | | - // layer that it can load more data on demand via the requestSnapshot method when, |
863 | | - // the syncMode = `on-demand` or `progressive` |
864 | | - const loadSubset = |
865 | | - syncMode === `eager` |
866 | | - ? undefined |
867 | | - : async (opts: LoadSubsetOptions) => { |
868 | | - // In progressive mode, stop requesting snapshots once full sync is complete |
869 | | - if (syncMode === `progressive` && hasReceivedUpToDate) { |
870 | | - return |
871 | | - } |
872 | | - const snapshotParams = compileSQL<T>(opts) |
873 | | - await stream.requestSnapshot(snapshotParams) |
874 | | - } |
875 | | - |
| 881 | + // Return the deduplicated loadSubset if available (on-demand or progressive mode) |
| 882 | + // The loadSubset method is auto-bound, so it can be safely returned directly |
876 | 883 | return { |
877 | | - loadSubset, |
| 884 | + loadSubset: loadSubsetDedupe?.loadSubset, |
878 | 885 | cleanup: () => { |
879 | 886 | // Unsubscribe from the stream |
880 | 887 | unsubscribeStream() |
|
0 commit comments