diff --git a/.changeset/live-query-gctime-zero.md b/.changeset/live-query-gctime-zero.md new file mode 100644 index 0000000000..ac199c4e55 --- /dev/null +++ b/.changeset/live-query-gctime-zero.md @@ -0,0 +1,5 @@ +--- +'@tanstack/db': patch +--- + +Preserve an explicit `gcTime: 0` on live query collections. The live query config builder used `this.config.gcTime || 5000`, so a `gcTime` of `0` (which disables garbage collection) was treated as unset and silently replaced by the 5s default, causing the collection to be garbage collected instead of kept alive. Use `??` so only `undefined` falls back to the default. diff --git a/packages/db/src/query/live/collection-config-builder.ts b/packages/db/src/query/live/collection-config-builder.ts index a6a51b4788..4d80b3fe17 100644 --- a/packages/db/src/query/live/collection-config-builder.ts +++ b/packages/db/src/query/live/collection-config-builder.ts @@ -248,7 +248,7 @@ export class CollectionConfigBuilder< sync: this.getSyncConfig(), compare: this.compare, defaultStringCollation: this.compareOptions, - gcTime: this.config.gcTime || 5000, // 5 seconds by default for live queries + gcTime: this.config.gcTime ?? 5000, // 5 seconds by default for live queries schema: this.config.schema, onInsert: this.config.onInsert, onUpdate: this.config.onUpdate, diff --git a/packages/db/tests/query/live-query-collection.test.ts b/packages/db/tests/query/live-query-collection.test.ts index 29d10cc27d..a2613c0104 100644 --- a/packages/db/tests/query/live-query-collection.test.ts +++ b/packages/db/tests/query/live-query-collection.test.ts @@ -449,6 +449,21 @@ describe(`createLiveQueryCollection`, () => { }) }) + it(`should forward an explicit gcTime of 0 (disable GC) instead of coercing it to the default`, () => { + const options = liveQueryCollectionOptions({ + query: (q) => + q + .from({ user: usersCollection }) + .where(({ user }) => eq(user.active, true)), + gcTime: 0, + }) + + // gcTime: 0 disables garbage collection. A `|| 5000` fallback treats the + // explicit 0 as unset and silently replaces it with the 5s default, so the + // collection is garbage collected instead of being kept alive. + expect(options.gcTime).toBe(0) + }) + it(`should not reuse finalized graph after GC cleanup (resubscribe is safe)`, async () => { const liveQuery = createLiveQueryCollection({ query: (q) =>