Skip to content

feat: $pendingOperation virtual prop#1431

Open
marbemac wants to merge 8 commits into
TanStack:mainfrom
marbemac:mbm/pending-operation-virtual-prop
Open

feat: $pendingOperation virtual prop#1431
marbemac wants to merge 8 commits into
TanStack:mainfrom
marbemac:mbm/pending-operation-virtual-prop

Conversation

@marbemac

@marbemac marbemac commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

🎯 Changes

Adds a new $pendingOperation virtual property to collection rows ('insert' | 'update' | 'delete' | null). This tells you what type of optimistic mutation is pending for each row, which is useful for building draft/review UIs where you want to show git-style change indicators, amongst other things.

Note, large-ish diff but most of it is new tests 😅.

The key feature: items deleted in a pending transaction can now stay visible in query results. By default nothing changes — deleted items still vanish from queries. But if your query references $pendingOperation in a .where() clause, the implicit filter is disabled and you can see pending-delete items inline:

// Default — deleted items hidden (same as before)
q.from({ task: tasks }).where(({ task }) => eq(task.projectId, projectId))

// Opt in — deleted items visible with $pendingOperation: 'delete'
q.from({ task: tasks }).where(({ task }) =>
  and(
    eq(task.projectId, projectId),
    or(isNull(task.$pendingOperation), not(isNull(task.$pendingOperation))),
  ),
)

Works with live queries, createEffect, joins/subqueries, GROUP BY, ordered/paginated queries, and selective where clauses like not(isNull($pendingOperation)) for "show only pending changes" views.

This was discussed with @samwillis beforehand — the approach is to keep deletes as deletes at the collection layer and convert them to updates at the subscription layer when opted in.

I also went ahead and built and linked into our actual app to test out the functionality. It's damn neat! For example, can show indicators inline for as yet uncommitted transaction. Imagine CRM app, and app with data grids w rows that can be updated/removed/etc, or really any productivity app that wants to allow humans and agents to safely make changes, and represent those changes inline in the application without having to change the data layer at all (note R and A badges on the files on the left, and the red bordered "install" that has been deleted but not yet "committed").

Screenshot 2026-03-29 at 7 45 41 PM

Notable behavioral change

isRowSynced() now also checks pendingOptimisticUpserts and pendingOptimisticDeletes, so $synced is false during the completed-but-awaiting-sync window. Previously it could briefly show $synced: true while a pending operation was still awaiting sync confirmation.

✅ Checklist

  • I have tested this code locally with pnpm test.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features

    • Added $pendingOperation virtual property tracking optimistic mutations (insert, update, delete) on collection rows, enabling pending-delete visibility in live queries, effects, grouped results, and joins when referenced in filter conditions.
  • Tests

    • Added comprehensive test coverage for $pendingOperation behavior across mutations, transactions, live queries, and query filtering.

marbemac and others added 6 commits March 29, 2026 19:41
… type

Add a new virtual property $pendingOperation ('insert' | 'update' | 'delete' | null)
to every collection row. This tells consumers what type of optimistic mutation is
pending, enabling draft/review UIs that show git-style change indicators.
- Subscription-layer delete-to-update conversion for opted-in queries
- Auto-detection of $pendingOperation in where clauses
- Initial snapshot includes pending-delete items
- Fix missing $pendingOperation in multi-group GROUP BY path
- Tighten string|null to PendingOperationType in group-by compiler
- Fix ?? vs !== undefined inconsistency for nullable $pendingOperation
- Add GROUP BY tests for $pendingOperation aggregation
… memory cleanup

- Fix stale $pendingOperation after rollback of optimistic delete by tracking
  converted delete values and converting rollback inserts to updates
- Fix isRowSynced to check pendingOptimistic* maps for consistency with
  getPendingOperation (prevents contradictory $synced: true + $pendingOperation: 'delete')
- Fix lazy source (join/subquery) pending deletes by merging child
  sourceWhereClauses into parent during query compilation
- Fix convertedDeleteValues memory leak: clean up on sync-confirmed delete,
  truncate, and unsubscribe
- Add computePendingOperation callback to enrichRowWithVirtualProps
Export expressionReferencesPendingOperation from collection-subscriber
and use it in effect.ts buildSubscriptionOptions to auto-detect
$pendingOperation references and set includePendingDeletes on the
subscription.
Signed-off-by: Marc MacLeod <marbemac+gh@gmail.com>
@marbemac

marbemac commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

One thing I considered but left out because wasn't sure if ya'll would be ok w a new API method. A .includePendingDeletes() method on the query builder. Since the tautology pattern is a little awkward for the "include everything including deleted items" use case, instead of:

.where(({ task }) =>
  and(
    eq(task.projectId, projectId),
    or(isNull(task.$pendingOperation), not(isNull(task.$pendingOperation))),
  ),
)

User could do:

.where(({ task }) => eq(task.projectId, projectId))
.includePendingDeletes()

OR alternative, just a simple exported util:

.where(({ task }) => includeDeletedItems(eq(task.projectId, projectId)))

If that's something you guys would consider, I can try and add it - don't think it'd be much code.

@pkg-pr-new

pkg-pr-new Bot commented Mar 30, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-db

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

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@1431

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@1431

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@1431

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@1431

@tanstack/electric-db-collection

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

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@1431

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@1431

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@1431

@tanstack/offline-transactions

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

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@1431

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@1431

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: afb1604

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces a $pendingOperation virtual property ('insert' | 'update' | 'delete' | null) on every collection row, derived from optimistic mutation state. When referenced in .where() clauses, pending-delete rows remain visible in live queries, effects, GROUP BY, and joins. Import ordering in several test files was also adjusted cosmetically.

Changes

$pendingOperation virtual property feature

Layer / File(s) Summary
PendingOperationType type & virtual-prop API contract
packages/db/src/virtual-props.ts, packages/db/src/types.ts, packages/db/src/index.ts, .changeset/pending-operation-virtual-prop.md
Defines PendingOperationType union, extends VirtualRowProps with $pendingOperation, updates createVirtualProps, enrichRowWithVirtualProps, computeAggregateVirtualProps, and VIRTUAL_PROP_NAMES; adds includePendingDeletes to SubscribeChangesOptions; re-exports the new type from the package index; adds changeset notes.
CollectionStateManager: pending operation computation & caching
packages/db/src/collection/state.ts
Adds getPendingOperation() deriving insert/update/delete/null from optimistic and pending-optimistic state; broadens isRowSynced; threads $pendingOperation through snapshot creation, virtual-props cache, enrichment calls, and sync-commit virtualChanged detection.
CollectionSubscription: pending-delete visibility & rollback
packages/db/src/collection/subscription.ts
Adds includePendingDeletes option, convertedDeleteValues map, convertPendingDeletes (delete→update with $pendingOperation:'delete', rollback insert→update), and appendPendingDeleteItems; wires into emitEvents, requestSnapshot, requestLimitedSnapshot, handleTruncate, and unsubscribe.
expressionReferencesPendingOperation & auto-detection in live queries / effects
packages/db/src/query/live/collection-subscriber.ts, packages/db/src/query/effect.ts
Adds exported expressionReferencesPendingOperation helper; wires it into subscribeToMatchingChanges, subscribeToOrderedChanges, and buildSubscriptionOptions so includePendingDeletes is set automatically when the where-clause references $pendingOperation.
GROUP BY compiler: $pendingOperation aggregation
packages/db/src/query/compiler/group-by.ts
Extends RowVirtualMetadata with pendingOperation; adds __virtual_pending_op__ virtual aggregator selecting the first non-null value across a group; writes result into $pendingOperation on single-group and multi-group result rows.
Test suite & test utilities
packages/db/tests/pending-operation.test.ts, packages/db/tests/utils.ts, packages/db/tests/collection-subscribe-changes.test.ts, packages/db-sqlite-persistence-core/tests/persisted.test.ts
Adds 1310-line test suite covering basic behavior, mutation merging, event transitions, cache invalidation, delete-visibility in live queries, GROUP BY, $synced consistency, rollback, joins, and createEffect; updates stripVirtualProps/omitVirtualProps and existing fixtures to include $pendingOperation.

Import ordering cosmetic changes

Layer / File(s) Summary
Import reordering in e2e and integration tests
packages/electric-db-collection/e2e/electric.e2e.test.ts, packages/electric-db-collection/tests/electric-live-query.test.ts, packages/query-db-collection/e2e/..., packages/react-db/tests/useLiveInfiniteQuery.test.tsx, packages/trailbase-db-collection/e2e/trailbase.e2e.test.ts
Reorders BasicIndex/BTreeIndex and createCollection in named imports across five test files; no logic or behavior changes.

Sequence Diagram(s)

sequenceDiagram
  participant LiveQuery
  participant CollectionSubscriber
  participant CollectionSubscription
  participant CollectionStateManager
  participant expressionReferencesPendingOperation

  LiveQuery->>CollectionSubscriber: subscribe(whereExpression)
  CollectionSubscriber->>expressionReferencesPendingOperation: whereExpression
  expressionReferencesPendingOperation-->>CollectionSubscriber: true (references $pendingOperation)
  CollectionSubscriber->>CollectionSubscription: subscribeChanges({includePendingDeletes: true})
  Note over CollectionSubscription: optimistic delete fires
  CollectionSubscription->>CollectionStateManager: getPendingOperation(key) → 'delete'
  CollectionSubscription->>CollectionSubscription: convertPendingDeletes — delete→update($pendingOperation:'delete')
  CollectionSubscription-->>LiveQuery: update event (row visible with $pendingOperation:'delete')
  Note over CollectionSubscription: sync confirms delete
  CollectionSubscription-->>LiveQuery: delete event (row removed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • kevin-dp
  • samwillis

Poem

🐇 A hop through the pending queue,
Where deleted rows still peek at you!
$pendingOperation lights the way —
'delete', 'insert', 'update' say.
Optimistic ops now tracked with care,
The rabbit left virtual breadcrumbs there! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: $pendingOperation virtual prop' clearly and concisely describes the main feature being added—the introduction of a new virtual property for tracking pending operations on collection rows.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the changes, motivation, use cases, implementation approach, and notable behavioral changes. Both checklist items are addressed: testing is confirmed and a changeset has been generated.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/db/src/collection/subscription.ts (1)

87-87: ⚡ Quick win

Replace any in convertedDeleteValues with a concrete row value type.

Using any here weakens type safety in the rollback conversion path.

♻️ Suggested typing cleanup
+type ConvertedDeleteValue = Record<string, unknown>
@@
-  private convertedDeleteValues = new Map<string | number, any>()
+  private convertedDeleteValues = new Map<string | number, ConvertedDeleteValue>()

As per coding guidelines, "**/*.{ts,tsx}: Avoid using any types; use unknown instead when the type is truly unknown, and provide proper type annotations for return values".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/src/collection/subscription.ts` at line 87, In the
convertedDeleteValues Map declaration, replace the any type parameter used for
the Map's values with a concrete row value type that represents the actual data
being stored in the rollback conversion path. If the specific type cannot be
determined, use unknown instead of any per the coding guidelines. Ensure proper
type annotations are provided for this Map to strengthen type safety throughout
the subscription class.

Source: Coding guidelines

packages/db/tests/pending-operation.test.ts (1)

954-963: 🏗️ Heavy lift

Reduce any usage in test query/effect wiring to preserve type safety.

These blocks rely on any for query builders, row aliases, and event payloads, which weakens compile-time checks in exactly the contracts this suite is validating. Introduce local typed aliases/helpers (for query row shapes and event values) and use unknown + narrowing only where unavoidable.

As per coding guidelines, “Avoid using any types; use unknown instead when the type is truly unknown, and provide proper type annotations for return values.”

Also applies to: 989-998, 1092-1102, 1188-1204, 1287-1297

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/tests/pending-operation.test.ts` around lines 954 - 963, Replace
excessive `any` type annotations with properly typed aliases and narrowed types
throughout the test file to improve type safety. Introduce local typed aliases
for query row shapes (such as the task item structure used in the groupBy and
select callbacks) and replace all `any` parameter annotations with either the
specific typed aliases or `unknown` with appropriate type narrowing. This change
applies to multiple locations in packages/db/tests/pending-operation.test.ts:
the query builder callback at lines 954-963, the effect wiring blocks at lines
989-998, 1092-1102, 1188-1204, and 1287-1297. For each location, identify what
data structure is being queried or processed and create a corresponding type
interface, then use that type instead of `any` in the callback parameters and
destructuring patterns.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/db/src/collection/subscription.ts`:
- Around line 424-446: The appendPendingDeleteItems method is adding all
pending-delete items to the changes array without verifying they match the
active whereExpression filter. This causes rows that fail the query predicate to
be incorrectly emitted in filtered queries, particularly those with predicates
on $pendingOperation. Before pushing the enriched value to the changes array,
check if the enriched value passes the active whereExpression filter (similar to
how other code paths in the class validate items against the query predicate),
and only add it if it matches. Apply this same filtering logic at the other two
locations mentioned in the comment where pending deletes are appended.

In `@packages/db/tests/pending-operation.test.ts`:
- Line 11: The waitForChanges function uses a hardcoded 10ms setTimeout delay,
making tests timing-sensitive and flaky. Replace this fixed-delay approach with
a deterministic mechanism that waits for actual observable state transitions,
such as awaiting a specific collection/query event, a promise that resolves when
data changes are detected, or a polling helper that checks for completion of
pending operations rather than relying on arbitrary time delays.

---

Nitpick comments:
In `@packages/db/src/collection/subscription.ts`:
- Line 87: In the convertedDeleteValues Map declaration, replace the any type
parameter used for the Map's values with a concrete row value type that
represents the actual data being stored in the rollback conversion path. If the
specific type cannot be determined, use unknown instead of any per the coding
guidelines. Ensure proper type annotations are provided for this Map to
strengthen type safety throughout the subscription class.

In `@packages/db/tests/pending-operation.test.ts`:
- Around line 954-963: Replace excessive `any` type annotations with properly
typed aliases and narrowed types throughout the test file to improve type
safety. Introduce local typed aliases for query row shapes (such as the task
item structure used in the groupBy and select callbacks) and replace all `any`
parameter annotations with either the specific typed aliases or `unknown` with
appropriate type narrowing. This change applies to multiple locations in
packages/db/tests/pending-operation.test.ts: the query builder callback at lines
954-963, the effect wiring blocks at lines 989-998, 1092-1102, 1188-1204, and
1287-1297. For each location, identify what data structure is being queried or
processed and create a corresponding type interface, then use that type instead
of `any` in the callback parameters and destructuring patterns.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be4fed18-8548-4356-b955-6e6bc39d01f5

📥 Commits

Reviewing files that changed from the base of the PR and between 4d1abde and a40f829.

📒 Files selected for processing (19)
  • .changeset/pending-operation-virtual-prop.md
  • packages/db-sqlite-persistence-core/tests/persisted.test.ts
  • packages/db/src/collection/state.ts
  • packages/db/src/collection/subscription.ts
  • packages/db/src/index.ts
  • packages/db/src/query/compiler/group-by.ts
  • packages/db/src/query/effect.ts
  • packages/db/src/query/live/collection-subscriber.ts
  • packages/db/src/types.ts
  • packages/db/src/virtual-props.ts
  • packages/db/tests/collection-subscribe-changes.test.ts
  • packages/db/tests/pending-operation.test.ts
  • packages/db/tests/utils.ts
  • packages/electric-db-collection/e2e/electric.e2e.test.ts
  • packages/electric-db-collection/tests/electric-live-query.test.ts
  • packages/query-db-collection/e2e/offline-refresh.e2e.test.ts
  • packages/query-db-collection/e2e/query.e2e.test.ts
  • packages/react-db/tests/useLiveInfiniteQuery.test.tsx
  • packages/trailbase-db-collection/e2e/trailbase.e2e.test.ts

Comment on lines +424 to +446
private appendPendingDeleteItems(
changes: Array<ChangeMessage<any, any>>,
): void {
const state = this.collection._state
const pendingDeleteKeys = new Set([
...state.optimisticDeletes,
...state.pendingOptimisticDeletes,
])
for (const key of pendingDeleteKeys) {
if (this.sentKeys.has(key)) continue
const syncedValue = state.syncedData.get(key)
if (syncedValue !== undefined) {
// enrichWithVirtualProps computes $pendingOperation via getPendingOperation(key),
// which returns 'delete' for keys in optimisticDeletes/pendingOptimisticDeletes.
const enrichedValue = state.enrichWithVirtualProps(syncedValue, key)
changes.push({
type: `insert` as const,
key,
value: enrichedValue,
})
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pending-delete append path bypasses active whereExpression filtering.

appendPendingDeleteItems adds all pending-delete keys from state, but these rows are not re-checked against the query predicate before being emitted. In filtered queries that reference $pendingOperation plus other predicates, this can leak rows that should not match.

🛠️ Proposed fix
-  private appendPendingDeleteItems(
-    changes: Array<ChangeMessage<any, any>>,
-  ): void {
+  private appendPendingDeleteItems(
+    changes: Array<ChangeMessage<any, any>>,
+    whereExpression?: BasicExpression<boolean>,
+  ): void {
     const state = this.collection._state
+    const whereFilter = whereExpression
+      ? createFilterFunctionFromExpression(whereExpression)
+      : undefined
     const pendingDeleteKeys = new Set([
       ...state.optimisticDeletes,
       ...state.pendingOptimisticDeletes,
@@
       const syncedValue = state.syncedData.get(key)
       if (syncedValue !== undefined) {
         const enrichedValue = state.enrichWithVirtualProps(syncedValue, key)
+        if (whereFilter && !whereFilter(enrichedValue)) {
+          continue
+        }
         changes.push({
           type: `insert` as const,
           key,
           value: enrichedValue,
         })
       }
     }
   }
-      this.appendPendingDeleteItems(snapshot)
+      this.appendPendingDeleteItems(snapshot, stateOpts.where)
-      this.appendPendingDeleteItems(changes)
+      this.appendPendingDeleteItems(changes, where)

Also applies to: 513-518, 666-670

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/src/collection/subscription.ts` around lines 424 - 446, The
appendPendingDeleteItems method is adding all pending-delete items to the
changes array without verifying they match the active whereExpression filter.
This causes rows that fail the query predicate to be incorrectly emitted in
filtered queries, particularly those with predicates on $pendingOperation.
Before pushing the enriched value to the changes array, check if the enriched
value passes the active whereExpression filter (similar to how other code paths
in the class validate items against the query predicate), and only add it if it
matches. Apply this same filtering logic at the other two locations mentioned in
the comment where pending deletes are appended.

import { mockSyncCollectionOptions, stripVirtualProps } from './utils'
import type { ChangeMessage } from '../src/types'

const waitForChanges = () => new Promise((resolve) => setTimeout(resolve, 10))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace fixed-delay waiting with a deterministic async signal.

Line 11 uses a hardcoded setTimeout(..., 10), which can make CI timing-sensitive and flaky under load. Prefer awaiting an explicit collection/query event or a reusable polling helper tied to observable state transitions.

As per coding guidelines, “Test corner cases including ... async race conditions,” fixed sleeps are brittle for race-sensitive test synchronization.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/tests/pending-operation.test.ts` at line 11, The waitForChanges
function uses a hardcoded 10ms setTimeout delay, making tests timing-sensitive
and flaky. Replace this fixed-delay approach with a deterministic mechanism that
waits for actual observable state transitions, such as awaiting a specific
collection/query event, a promise that resolves when data changes are detected,
or a polling helper that checks for completion of pending operations rather than
relying on arbitrary time delays.

Source: Coding guidelines

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant