@tanstack/electric-db-collection 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/electric.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  and,
12
12
  validateSyncPersistenceCapability,
13
13
  warnOnce,
14
+ whenSyncAccepted,
14
15
  withCollectionConfigFactory,
15
16
  withCollectionSyncConfigCleanup,
16
17
  withCollectionSyncConfigFactory,
@@ -717,10 +718,12 @@ function createLoadSubsetDedupe<T extends Row<unknown>>({
717
718
  const snapshotParams = compileSQL<T>(opts, compileOptions)
718
719
  try {
719
720
  const { data: rows } = await stream.fetchSnapshot(snapshotParams)
720
- if (opts.signal?.aborted || !isBufferingInitialSync()) {
721
+ if (!isBufferingInitialSync()) {
721
722
  debug(`${logPrefix}Ignoring snapshot - sync completed while fetching`)
722
723
  return
723
724
  }
725
+ // Check the signal before commit to discard a stale snapshot.
726
+ throwIfAborted()
724
727
 
725
728
  if (rows.length > 0) {
726
729
  begin()
@@ -737,12 +740,16 @@ function createLoadSubsetDedupe<T extends Row<unknown>>({
737
740
  debug(`${logPrefix}Applied snapshot with ${rows.length} rows`)
738
741
  }
739
742
  } catch (error) {
740
- if (opts.signal?.aborted) return
743
+ // Cleanup is quiet; a caller that aborted sees `AbortError`.
741
744
  if (handleSnapshotError(error, `fetchSnapshot`)) {
742
745
  return
743
746
  }
747
+ if (opts.signal?.aborted) throw abortReason(opts.signal)
744
748
  throw error
745
749
  }
750
+ // Rows accepted before an abort still apply, but the caller that
751
+ // aborted sees `AbortError`.
752
+ if (opts.signal?.aborted) throw abortReason(opts.signal)
746
753
  return
747
754
  }
748
755
 
@@ -1922,9 +1929,10 @@ function createElectricSync<T extends Row<unknown>>(
1922
1929
  return applied
1923
1930
  }
1924
1931
 
1932
+ // Subset hydration must not split a stream transaction it overlaps.
1925
1933
  const beginSourceTransaction = () => {
1926
- if (metadata?.persistence) begin({ immediate: true })
1927
- else begin()
1934
+ begin()
1935
+ metadata?.persistence?.reserveCommitTurn()
1928
1936
  }
1929
1937
 
1930
1938
  // Track keys that have been synced to handle overlapping subset queries.
@@ -1966,7 +1974,7 @@ function createElectricSync<T extends Row<unknown>>(
1966
1974
  lifecycle.resumeState = resetState
1967
1975
 
1968
1976
  if (metadata) {
1969
- begin({ immediate: true })
1977
+ begin()
1970
1978
  metadata.collection.set(`electric:resume`, resetState)
1971
1979
  if (expectInResumeSnapshot) {
1972
1980
  expectCurrentCommit?.()
@@ -2000,8 +2008,7 @@ function createElectricSync<T extends Row<unknown>>(
2000
2008
 
2001
2009
  // Extract active_conditions from headers (DNF support)
2002
2010
  const activeConditions = changeMessage.headers.active_conditions as
2003
- | ActiveConditions
2004
- | undefined
2011
+ ActiveConditions | undefined
2005
2012
 
2006
2013
  const rowId = collection.getKeyFromItem(changeMessage.value)
2007
2014
  const operation = changeMessage.headers.operation
@@ -2415,12 +2422,20 @@ function createElectricSync<T extends Row<unknown>>(
2415
2422
  }
2416
2423
  }
2417
2424
  const readyErrorVersion = streamErrorVersion
2418
- if (applied === true) {
2425
+ // Readiness counts accepted rows.
2426
+ const accepted = whenSyncAccepted(applied)
2427
+ if (accepted === true) {
2419
2428
  wrappedMarkReady(wasBufferingInitialSync, readyErrorVersion)
2420
2429
  } else {
2421
- void applied.then(
2430
+ void accepted.then(
2422
2431
  () =>
2423
2432
  wrappedMarkReady(wasBufferingInitialSync, readyErrorVersion),
2433
+ () => undefined,
2434
+ )
2435
+ }
2436
+ if (applied !== true) {
2437
+ void applied.then(
2438
+ () => undefined,
2424
2439
  (error: unknown) => {
2425
2440
  if (!isActiveLifecycle() || abortController.signal.aborted) {
2426
2441
  return