Skip to content

Conversation

@KyleAMathews
Copy link
Collaborator

@KyleAMathews KyleAMathews commented Jan 15, 2026

Summary

Fixes a bug where setting gcTime: Infinity to disable garbage collection actually caused immediate GC instead of never collecting, due to JavaScript's setTimeout coercing Infinity to 0 via ToInt32.


Root Cause

When users configure gcTime: Infinity expecting their collection to never be garbage collected, JavaScript's setTimeout silently converts the delay:

setTimeout(fn, Infinity)  // Actually executes as setTimeout(fn, 0)

This happens because the HTML spec requires the delay to be clamped to a 32-bit signed integer, and ToInt32(Infinity) === 0. The result: collections were immediately cleaned up the moment subscribers dropped to zero—the exact opposite of the intended behavior.

Approach

Added an explicit check for non-finite values alongside the existing gcTime === 0 check:

if (gcTime === 0 || !Number.isFinite(gcTime)) {
  return  // Don't start GC timer
}

Using Number.isFinite() handles Infinity, -Infinity, and NaN in a single check, making the code robust against any edge cases.

Key Invariants

  • gcTime: 0 → GC disabled (existing behavior, unchanged)
  • gcTime: Infinity → GC disabled (now works correctly)
  • gcTime: <positive number> → GC after specified milliseconds (unchanged)

Non-goals

  • Didn't change the default gcTime value (5 minutes)
  • Didn't add warnings for unusual gcTime values—the API contract is clear

Trade-offs

Alternative considered: Could have special-cased only Infinity, but !Number.isFinite() is more defensive against NaN or negative infinity edge cases that would also misbehave with setTimeout.


Verification

pnpm test packages/db/tests/collection-lifecycle.test.ts

The new test case specifically validates that gcTime: Infinity prevents any timer from being scheduled.

Files Changed

File Change
packages/db/src/collection/lifecycle.ts Added !Number.isFinite(gcTime) check in startGCTimer()
packages/db/tests/collection-lifecycle.test.ts Added test case for gcTime: Infinity behavior

🤖 Generated with Claude Code

When gcTime was set to Infinity, setTimeout(fn, Infinity) would coerce
Infinity to 0 via JavaScript's ToInt32 conversion, causing immediate
garbage collection instead of disabling it.

This fix treats Infinity (and any non-finite values) the same as 0,
effectively disabling automatic garbage collection when the user intends
for data to never be collected.

Fixes issue where collections in Electron apps would unexpectedly lose
data when navigating back and forth with gcTime set to Infinity.
@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

🦋 Changeset detected

Latest commit: 4c988df

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@tanstack/db Patch
@tanstack/angular-db Patch
@tanstack/electric-db-collection Patch
@tanstack/offline-transactions Patch
@tanstack/powersync-db-collection Patch
@tanstack/query-db-collection Patch
@tanstack/react-db Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 15, 2026

More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@1135

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@1135

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@1135

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@1135

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@1135

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@1135

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@1135

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@1135

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@1135

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@1135

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@1135

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@1135

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@1135

commit: 4c988df

@github-actions
Copy link
Contributor

Size Change: +14 B (+0.02%)

Total Size: 90.6 kB

Filename Size Change
./packages/db/dist/esm/collection/lifecycle.js 1.68 kB +14 B (+0.84%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 1.19 kB
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/index.js 3.32 kB
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/mutations.js 2.34 kB
./packages/db/dist/esm/collection/state.js 3.46 kB
./packages/db/dist/esm/collection/subscription.js 3.62 kB
./packages/db/dist/esm/collection/sync.js 2.38 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.49 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/index.js 2.69 kB
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 1.93 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 513 B
./packages/db/dist/esm/local-only.js 837 B
./packages/db/dist/esm/local-storage.js 2.1 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 4.08 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 1.05 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.42 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 1.87 kB
./packages/db/dist/esm/query/compiler/index.js 1.96 kB
./packages/db/dist/esm/query/compiler/joins.js 2 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.45 kB
./packages/db/dist/esm/query/compiler/select.js 1.06 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.4 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 1.93 kB
./packages/db/dist/esm/query/live/internal.js 145 B
./packages/db/dist/esm/query/optimizer.js 2.56 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 B
./packages/db/dist/esm/scheduler.js 1.3 kB
./packages/db/dist/esm/SortedMap.js 1.3 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 247 B
./packages/db/dist/esm/strategies/queueStrategy.js 428 B
./packages/db/dist/esm/strategies/throttleStrategy.js 246 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 924 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 852 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

Size Change: 0 B

Total Size: 3.47 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.12 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 559 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

compressed-size-action::react-db-package-size

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

3 participants