Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

Garbage collection cleans up a collection while one of its transactions is still persisting

Ouverte
#2,256 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@Nabil372 y travaille déjà.

Depuis le 24/10/2026.

  • #2 par @Nabil372 — ouverte
  • #2258 par @Nabil372 — ouverte

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
35/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
typescript
Domaine
database

Piste de recherche

Start with packages/db/src/collection/lifecycle.ts and trace how canGarbageCollect() determines whether cleanup can proceed. Then inspect the transaction lifecycle and existing generated-history tests mentioned in the issue. Done means a persisting transaction keeps the collection and its optimistic state alive until it settles or rolls back, while explicit cleanup() retains its current behavior.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

  • I've validated the bug against the latest version of DB packages

(Checked on main and on 0.15.2.)

Describe the bug

A collection with no subscribers is garbage collected after gcTime even when one of its transactions is still persisting. The optimistic row disappears while the mutation handler is still running. With the Electric collection, cleanup also rejects the handler's pending awaitTxId with StreamAbortedError, so the write fails even though the server accepted it.

We use TanStack DB with Electric in production in web apps and in Expo apps on iOS and Android, and this is easy to hit on mobile. A screen inserts a row and closes; the handler is waiting on a slow request, or on a txid that arrives late because the app went to the background. Once gcTime passes, the write is lost from the client's point of view.

canGarbageCollect() in packages/db/src/collection/lifecycle.ts checks for a cleanup in progress, active subscribers, and a pending preload, but not for persisting transactions.

To Reproduce

import { createCollection } from '@tanstack/db'

let release!: () => void
const handlerDone = new Promise<void>((resolve) => (release = resolve))

const collection = createCollection<{ id: string }, string>({
  id: 'gc-during-persist',
  getKey: (row) => row.id,
  gcTime: 10,
  startSync: true,
  sync: {
    sync: ({ markReady }) => {
      markReady()
      return () => {}
    },
  },
  onInsert: async () => {
    await handlerDone
  },
})

const subscription = collection.subscribeChanges(() => {})
const tx = collection.insert({ id: 'a' })
subscription.unsubscribe()

await new Promise((resolve) => setTimeout(resolve, 2000))
console.log(collection.status, collection.has('a'), tx.state)
// cleaned-up false persisting
release()

Expected behavior

While a transaction that touches the collection is persisting, the collection is not garbage collected, so its optimistic state and any awaitTxId or awaitMatch wait survive until the transaction settles. GC can start its timer once the transaction completes or rolls back. An explicit cleanup() would keep its current behavior.

In production we work around it by holding the collection with a subscription for the length of each write, using subscribeChanges(() => {}, { includeInitialState: false, deferAcquisition: true }) so the hold does not count as a reader. deferAcquisition is marked @internal, so we would rather not depend on it.

If holding a collection while its transaction persists is not the intended behavior, a public way to hold a collection for the length of a write would cover the same need.

I have a fix with a generated-history test and will open a pull request for it.

Desktop: Node 24, jsdom (Vitest). Smartphone: React Native (Expo), iOS and Android, where screens close and apps background while writes are in flight.

Langage dominant
TypeScript
Étoiles
4k
Forks
277
Merge moyen
17 h 40 min
PR mergées (30 j)
223

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de TanStack/db

Toutes les issues de TanStack/db

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.