Skip to content

Conversation

KyleAMathews
Copy link
Collaborator

Summary

Implements GitHub issue #402 by adding flexible matching strategies for electric-db-collection synchronization.

Txid Strategy (existing, backward compatible) - Uses PostgreSQL transaction IDs for precise matching
Custom Match Function Strategy (new) - Allows heuristic-based matching with custom logic
Void/Timeout Strategy (new, 3-second default) - Simple timeout for prototyping

Key Features

  • New types: MatchFunction<T>, MatchingStrategy<T>
  • Enhanced ElectricCollectionConfig to support all strategies
  • New utility: awaitMatch(matchFn, timeout?)
  • Export isChangeMessage and isControlMessage helpers for custom match functions
  • Comprehensive test coverage for all strategies
  • Updated documentation with detailed examples and migration guide

Benefits

  • Backward Compatibility: Existing code works unchanged
  • Architecture Flexibility: Choose the best strategy for your backend capabilities
  • Progressive Enhancement: Start with void strategy, upgrade to txid when ready
  • No Forced Backend Changes: Custom match functions work without backend modifications

Test plan

  • All existing tests pass
  • New tests for all three matching strategies
  • Timeout behavior testing
  • Backward compatibility verification
  • Integration tests with Electric stream simulation
  • Linting and type checking passes

🤖 Generated with Claude Code

- Add three matching strategies for client-server synchronization:
  1. Txid strategy (existing, backward compatible)
  2. Custom match function strategy (new)
  3. Void/timeout strategy (new, 3-second default)

- New types: MatchFunction<T>, MatchingStrategy<T>
- Enhanced ElectricCollectionConfig to support all strategies
- New utility: awaitMatch(matchFn, timeout?)
- Export isChangeMessage and isControlMessage helpers
- Remove deprecated error classes (beta compatibility not required)
- Comprehensive tests for all strategies including timeout behavior
- Updated documentation with detailed examples and migration guide

Benefits:
- Backward compatibility maintained
- Architecture flexibility for different backend capabilities
- Progressive enhancement path
- No forced backend API changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Copy link

changeset-bot bot commented Sep 3, 2025

🦋 Changeset detected

Latest commit: 2ca6beb

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

This PR includes changesets to release 2 packages
Name Type
@tanstack/electric-db-collection Minor
@tanstack/db-example-react-todo 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

Copy link

pkg-pr-new bot commented Sep 3, 2025

More templates

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: 2ca6beb

Copy link
Contributor

github-actions bot commented Sep 3, 2025

Size Change: 0 B

Total Size: 66.6 kB

ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/change-events.js 1.13 kB
./packages/db/dist/esm/collection.js 10.5 kB
./packages/db/dist/esm/deferred.js 230 B
./packages/db/dist/esm/errors.js 3.1 kB
./packages/db/dist/esm/index.js 1.55 kB
./packages/db/dist/esm/indexes/auto-index.js 745 B
./packages/db/dist/esm/indexes/base-index.js 605 B
./packages/db/dist/esm/indexes/btree-index.js 1.74 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.25 kB
./packages/db/dist/esm/local-only.js 827 B
./packages/db/dist/esm/local-storage.js 2.03 kB
./packages/db/dist/esm/optimistic-action.js 294 B
./packages/db/dist/esm/proxy.js 3.87 kB
./packages/db/dist/esm/query/builder/functions.js 615 B
./packages/db/dist/esm/query/builder/index.js 3.93 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 938 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.52 kB
./packages/db/dist/esm/query/compiler/expressions.js 631 B
./packages/db/dist/esm/query/compiler/group-by.js 2.08 kB
./packages/db/dist/esm/query/compiler/index.js 2.27 kB
./packages/db/dist/esm/query/compiler/joins.js 2.5 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.23 kB
./packages/db/dist/esm/query/compiler/select.js 1.28 kB
./packages/db/dist/esm/query/ir.js 508 B
./packages/db/dist/esm/query/live-query-collection.js 333 B
./packages/db/dist/esm/query/live/collection-config-builder.js 2.59 kB
./packages/db/dist/esm/query/live/collection-subscriber.js 2.4 kB
./packages/db/dist/esm/query/optimizer.js 3.05 kB
./packages/db/dist/esm/SortedMap.js 1.24 kB
./packages/db/dist/esm/transactions.js 2.29 kB
./packages/db/dist/esm/utils.js 943 B
./packages/db/dist/esm/utils/btree.js 6.02 kB
./packages/db/dist/esm/utils/comparison.js 718 B
./packages/db/dist/esm/utils/index-optimization.js 1.62 kB

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

Copy link
Contributor

github-actions bot commented Sep 3, 2025

Size Change: 0 B

Total Size: 1.18 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 152 B
./packages/react-db/dist/esm/useLiveQuery.js 1.02 kB

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

KyleAMathews and others added 4 commits September 3, 2025 15:35
…nd API consistency

Critical fixes based on thorough code review:

**🔧 Commit Semantics Fix:**
- awaitMatch now waits for up-to-date after finding match (like awaitTxId)
- Ensures consistent behavior between txid and custom match strategies
- Prevents race conditions where mutations marked "persisted" before actual commit

**🧠 Memory Leak Fixes:**
- Properly cleanup pendingMatches on timeout and abort
- Add abort listener to cleanup all pending matches on stream abort
- Use cross-platform ReturnType<typeof setTimeout> instead of NodeJS.Timeout

**🎯 API Consistency:**
- Unified MatchingStrategy type used across all handler return types
- Support configurable timeout for void strategy: { timeout: 1500 }
- Remove unused discriminator type field for cleaner duck-typed unions

**🧪 Enhanced Test Coverage:**
- Test memory cleanup after timeout (no lingering handlers)
- Test commit semantics (awaitMatch waits for up-to-date)
- Test configurable void timeout functionality
- All edge cases now properly covered

**📦 Version Bump:**
- Changeset updated to minor (removed exported error classes)

All feedback addressed while maintaining backward compatibility.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Based on engineering feedback, this commit addresses several critical edge cases:

**Memory Safety & Error Handling:**
- Fix timeout cleanup memory leak in awaitMatch - pending matchers now properly removed on timeout
- Add try/catch around matchFn calls to prevent user code from crashing stream loop
- Add proper abort semantics with StreamAbortedError for pending matches
- Add TimeoutWaitingForMatchError following codebase error class conventions

**Race Condition Fix:**
- Implement up-to-date bounded message buffer to handle race where messages arrive before matcher registration
- Buffer is safely bounded to current transaction batch, eliminating stale data matching risks
- Messages cleared on each up-to-date to maintain transaction boundaries

**Test Reliability:**
- Replace timing-based assertions with fake timers using vi.runOnlyPendingTimersAsync()
- Eliminates CI flakiness while testing the same void strategy functionality

**Cross-platform Compatibility:**
- Confirmed ReturnType<typeof setTimeout> usage for browser compatibility
- API shape consistency already matches runtime behavior

The core matching strategy design (txid/custom/void) remains unchanged - these are
lifecycle polish fixes for production readiness.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
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