- ADD
getConnectionHandlerNostr()to the WebRTC replication plugin. Peers find each other over Nostr relays instead of a signaling server. Signals are sent as signed, NIP-44 encrypted ephemeral events, andgetNostrPublicKeyOfPeer()returns the verified public key of a peer for use inisPeerValid(). Added tests for the Nostr signaling with multiple relays, peer validation and unreachable relays. - FIX DenoKV RxStorage: a query without a
limitpassedInfinitytoDeno.Kv.list(), which throwsLimit must be a positive integersince Deno 2.9. Unlimited queries no longer pass a limit at all. - FIX
DocumentCache: a document that is re-inserted after the cleanup purged its tombstone was no longer found byfindOne()and by primary key queries, because the new revision chain starts at height1and the out-of-order protection kept the cached tombstone. #8948 - FIX typos in the dev-mode error messages:
DB6had the docs URL glued to the sentence (Read thishttps://...),GDR18saidexxeededinstead ofexceeded, andMQ4saidinstanceofinstead ofinstance of. - FIX
IncrementalWriteQueue: ensure storagebulkWriteerrors are properly caught and reset queue runner state so the queue does not wedge on failure. - FIX schema migration finalized with
Promise.all([oldStorage.remove(), metaStorage.remove()])which removed both storage instances at the same time. Storages like SQLite share a single connection between all storage instances of one database, so the twoDROP TABLEstatements were sent to the same connection concurrently and async single-connection adapters like expo-sqlite failed withSQLITE_LOCKED("database is locked"). The storages are now removed one after another and theDROP TABLEof the SQLite RxStorage runs inside of a transaction so that it goes throughTX_QUEUE_BY_DATABASE. Added a test case that tracks overlapping statements on a single SQLite connection. Fixes #9024. - FIX schema migration with
multiInstance: trueblockedaddCollections()in every tab forever when the tab that won the leader election of the migration was frozen, throttled or discarded by the browser. The migration leader now writes a heartbeat into the migration status document and waiting tabs take over the migration when the status document was not written for 60 seconds (configurable withsetMigrationLeaderTiming()). Fixes #9191. - FIX flaky preact-signals reactivity test that asserted the signal value before the change event of the
remotestorage arrived #9172 - FIX query-builder:
.where({ age: { $gt: 3 } })on a query whose selector had a shorthand value for the same field (for examplefind({ selector: { age: 7 } })) threwTypeError: Cannot create property '$gt' on number '7'. In the other direction,.where({ age: 7 })silently dropped an existing operator like{ $lt: 7 }. The shorthand value is now converted to$eqso both conditions are merged. Added a test case intest/unit/query-builder.test.ts. - FIX replication: when the first
start()of a replication rejected, the error was an unhandled rejection that was not emitted onerror$, and every laterstart(),pause()andremove()rejected with the same error because thestartQueuestayed rejected, so the replication could not be started again without a page reload. A failed start is now emitted onerror$asRC_STARTand a laterstart()retries it. The internalstart()calls ofautoStartandtoggleOnDocumentVisibleno longer create unhandled rejections. Added a test case for it intest/unit/replication.test.ts. Fixes #9127. - FIX replication-protocol: the upstream initial sync could call
getChangedDocumentsSince()on the forkRxStorageInstanceafter the replication was canceled, because it did not re-check the canceled state after it throttled on the runningpersistToMaster()promises. With a fast storage (rxdb-premium IndexedDB) this happened when a schema migration was interrupted viaRxMigrationState.cancel()which closes the old storage, so the "instance is closed" error ended up as an unhandled rejection. Added a testcase for it intest/unit/replication-protocol.test.ts. - FIX
addCollections()threwDB6for an unchanged schema after the device or app language changed.sortObject()useslocaleCompare(), so in Czech and Slovak ("ch" sorts after "h") the schema hash differed. When the hashes differ, the stored schema is now compared withdeepEqual()and no error is thrown when the content is equal. #9128 - FIX queries that sort by a nested field (for example
sort: [{ 'address.city': 'asc' }]) threwTypeError: Cannot read properties of nullwhen a document hadnullas the value of the parent object (address: null). The nested path lookup now treats anullparent like a missing one. Added a test case intest/unit/rx-query.test.ts. - FIX react plugin
useRxDocumentstarting withloading: falseinstead ofloading: truewhen valid collection and primaryKey are provided. This caused a false "not found" flash on the first render before the subscription resolved. Added equivalent tests to the existing react-hooks test suite. Fixes #8965. - FIX webmcp plugin causing an unhandled promise rejection when a collection is closed directly after
registerWebMCP()on a spec-conformantmodelContextwhoseregisterTool()returns a promise #9172 - FIX WebRTC replication was flaky and could spin or stop syncing:
- The simple-peer connection handler reconnected to the signaling server in a tight loop without delay and crashed in Node.js when the server was not reachable. Reconnects now use an exponential backoff.
- A failed peer connection was recreated in an endless loop. Peer connections now have a connect timeout, reconnect with a backoff, and signals of outdated connection attempts are ignored instead of throwing.
- The first replication request of a peer could get lost when it arrived before the own handshake was done, which made the sync hang forever. Requests are now answered independently of the handshake state.
- Requests to a disconnected peer never resolved. They now fail on disconnect, on timeout (new
requestTimeoutoption) and when the remote peer throws, so the replication retries. - With three or more peers, change stream events of one master were applied to the replications of all other masters.
- Messages bigger than the data channel size limit failed. They are now split into chunks.
- The signaling server now tells the other peers of a room when a peer leaves.
- Re-enabled the WebRTC replication tests and added tests for an unreachable signaling server, a signaling server restart and big documents with three peers.
RxWebRTCReplicationPool.cancel()now awaits the cancelation of all replications, so they do not write to the storage after the database was closed.
- FIX replication-protocol: when the upstream had push conflicts,
persistToMaster()wrote the resolved conflicts to the fork and meta instance even when the replication was canceled while the conflicts were resolved. This caused "already closed" errors when a database was closed during a replication. - IMPROVE performance of
findByIds(): the query cache key is no longer built from a sorted copy of all ids. With3000ids,find-by-idsin the memory performance test went from 4.80ms to 3.26ms. Queries with the same ids in a different order now get their own cache entry, so each resultMapkeeps the order of its own ids. - IMPROVE performance of the
DocumentCache: RxDocuments are cached by their revision, and the_meta.lwtis compared on lookup instead of being converted to a string for the cache key.find-by-querywent from 3.32ms to 2.60ms. - IMPROVE performance of nested property access on RxDocuments: the nested value is no longer looked up again from the document root on each access.
property-accesswent from 6.57ms to 4.02ms. - IMPROVE query planner: string and number fields that are matched with
$eqare ignored when checking whether the index order matches the sort order, as was already done for boolean and enum fields. The storage no longer has to re-sort these query results.find-by-query-parallel-4went from 3.63ms to 2.87ms. - IMPROVE performance of database and collection creation: schema hashes are cached, so the same schema is not hashed again for each collection or database.
time-to-first-insertwent from 1.40ms to 1.22ms. - FIX flaky
attachments.test.tsencryption test that decoded binary ciphertext as base64 and failed about 1 in 4 runs with storages that store the encrypted attachment data as binary #9193 - FIX the storage test
should clean up all deleted documents when multiple are deletedfailed from time to time when the storage uses another instance ofnow()than the test, like the premium storages in their integration tests. The test now waits until the deletion time is in the past before it runscleanup(0). - ADD tests that parallel
bulkWrite()calls and a schema migration with multiple batches keep all documents whenmultiInstance: falseis used. See #9145 - FIX
webmcp.test.tsfailed in browsers with native WebMCP support (like Chromium 154) because the polyfill does not install its testing shim whendocument.modelContextalready exists. The test now removes the native getter while it runs and restores it afterwards.
RxDB Server
- FIX the replication test
create read update deletedid not cancel its live replication before it closed the databases. The replication kept pulling from the closed server andensureReplicationHasNoErrors()threwfetch failedwhile the next test (should give a 426 error on outdated versions) was running, which made that test fail from time to time.
RxDB Premium
- FIX (storage-filesystem-node, storage-opfs and all other filesystem based storages) Multiple writes within the same write-run all wrote to
changes.jsonat offset 0 instead of appending, which left invalid JSON on disk while the run was in flight. When the process was killed in that window, the database could no longer be opened (SyntaxError: Expected ',' or ']' after array element in JSON). - FIX (storage-filesystem-node, storage-opfs and all other filesystem based storages) When the process died during a cleanup after the index files were written but before the
changelog.txtwas emptied, the next start applied the changelog operations a second time on top of the already updated index files. This corrupted the index state (lost documents, duplicated rows with stale byte positions) and the next cleanup or read failed withSyntaxError: Expected ',' or ']' after array element in JSON at position .... The changelog now starts with an epoch header and the index files remember the epoch and the amount of operations they already contain, so operations are never applied twice. Index and changelog files of older versions are still readable. - FIX (storage-memory-mapped) Fixed a bug where
bulkUpsertof an existing document would not survive a database reopen. The background persistence flush usedreturninstead ofcontinueinside the write-tasks loop, causing any remaining batched writes to be silently dropped whenever one write task produced no written documents (e.g. when a conflicting insert yields an empty result). See rxdb-premium-issues#24 - FIX (storage-indexeddb) With
multiInstance: false, parallelbulkWrite()calls with more than 16 documents overwrote each other's WAL content, so whole batches were lost without an error. This dropped documents during schema migrations that needed three or more batches. See #9145 - FIX (storage-indexeddb) Eliminated unhandled
TransactionInactiveErrorrejections that occurred during bulk replication pulls when concurrent reads hit the WAL flush window. See #8497
NOTICE: An overview about all releases can be found at the changelog