From b3eee0b9237b41f45b9597a8852947c3bbb485d7 Mon Sep 17 00:00:00 2001 From: Artem Litchmanov Date: Thu, 20 Aug 2026 15:31:42 -0700 Subject: [PATCH 1/2] port upstream #7875: stamp downstream origin marker, bypass false conflict skip The downstream skips a pulled document when the fork state differs from the assumed master state, on the assumption that a local write is waiting for the upstream to resolve it. A lost meta write or a crash between the fork write and the meta write produces the same difference without any local write, so the document is skipped on every later pull while the checkpoint keeps advancing. The downstream now records the origin of its own fork writes in _meta.o (identifier hash plus the revision height it is about to write). When fork and assumed master differ but the marker matches the current fork revision, the difference came from the downstream itself, so the skip is bypassed and the pulled document is applied. A local write bumps the revision height and voids the marker, so real local writes are still protected. Co-Authored-By: Claude Fable 5 --- src/replication-protocol/downstream.ts | 39 ++++-- src/types/rx-document.d.ts | 12 +- src/types/util.d.ts | 9 +- test/unit/replication.test.ts | 160 +++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 10 deletions(-) diff --git a/src/replication-protocol/downstream.ts b/src/replication-protocol/downstream.ts index 715aac70f01..81f5e76a9a4 100644 --- a/src/replication-protocol/downstream.ts +++ b/src/replication-protocol/downstream.ts @@ -345,19 +345,31 @@ export async function startReplicationDownstream { diff --git a/src/types/util.d.ts b/src/types/util.d.ts index 2a9dbdbb495..b00f88e5c5e 100644 --- a/src/types/util.d.ts +++ b/src/types/util.d.ts @@ -3,7 +3,14 @@ import type { RxStorage } from './rx-storage.interface'; export type MaybePromise = Promise | T; -export type PlainJsonValue = string | number | boolean | PlainSimpleJsonObject | PlainSimpleJsonObject[] | PlainJsonValue[]; +export type PlainJsonValue = + string | + number | + boolean | + PlainSimpleJsonObject | + PlainSimpleJsonObject[] | + PlainJsonValue[] | + { [key: string]: PlainJsonValue; }; export type PlainSimpleJsonObject = { [k: string]: PlainJsonValue | PlainJsonValue[]; }; diff --git a/test/unit/replication.test.ts b/test/unit/replication.test.ts index c1b23e39124..8836cc6f5bb 100644 --- a/test/unit/replication.test.ts +++ b/test/unit/replication.test.ts @@ -935,6 +935,166 @@ describe('replication.test.ts', () => { }); }); describeParallel('issues', () => { + /** + * @link https://github.com/pubkey/rxdb/pull/7804 + */ + function setupDownstreamTestReplication( + local: RxCollection, + remote: RxCollection + ) { + return replicateRxCollection({ + collection: local, + replicationIdentifier: 'downstream-test', + live: true, + pull: { + handler: getPullHandler(remote), + stream$: getPullStream(remote) + }, + push: { + handler: getPushHandler(remote) + } + }); + } + + /** + * Simulates a crash between fork write and meta write in downstream. + * + * When the process dies after forkInstance.bulkWrite() succeeds but before + * metaInstance.bulkWrite() completes, the fork has the new state but the + * assumed master in meta is stale. On the next downstream cycle, this + * mismatch is detected as a "non-upstream-replicated local write" and the + * document is skipped - expecting upstream to resolve the conflict. But + * upstream never picks it up because the fork write came from downstream, + * leaving the document permanently stuck. + */ + it('#7804 (1/2) should recover downstream sync after meta write is lost between fork and meta write (simulated crash)', async () => { + const { localCollection, remoteCollection } = await getTestCollections({ local: 0, remote: 0 }); + const docId = 'crash-test-doc'; + + // Insert initial document on remote + await remoteCollection.insert(schemaObjects.humanWithTimestampData({ + id: docId, + name: 'Initial', + age: 1 + })); + + // Start replication and let it sync the initial document + const replicationState = setupDownstreamTestReplication(localCollection, remoteCollection); + ensureReplicationHasNoErrors(replicationState); + await replicationState.awaitInitialReplication(); + + // Verify initial sync + const initialLocal = await localCollection.findOne(docId).exec(true); + assert.strictEqual(initialLocal.name, 'Initial'); + + // Monkey-patch metaInstance.bulkWrite to silently drop the next + // downstream meta write - simulating a crash between fork and meta write. + const metaInstance = ensureNotFalsy(replicationState.internalReplicationState).input.metaInstance; + const originalBulkWrite = metaInstance.bulkWrite.bind(metaInstance); + let metaWriteDropped = false; + + metaInstance.bulkWrite = function (rows: any[], context: string) { + if (context === 'replication-down-write-meta' && !metaWriteDropped) { + metaWriteDropped = true; + // Silently swallow the write: fork already persisted, meta is lost. + return Promise.resolve({ success: [], error: [] }); + } + return originalBulkWrite(rows, context); + } as any; + + // Update the document on remote. + // Downstream will write the new state to the fork, but the + // corresponding meta write is silently dropped above. + const remoteDoc = await remoteCollection.findOne(docId).exec(true); + const internalState = ensureNotFalsy(replicationState.internalReplicationState); + let prevDown = internalState.streamQueue.down; + await remoteDoc.incrementalPatch({ + name: 'FirstUpdate', + age: 2 + }); + + // Wait for the downstream cycle to finish + await waitUntil(() => internalState.streamQueue.down !== prevDown, undefined, 40); + await internalState.streamQueue.down; + + assert.ok(metaWriteDropped, 'Meta write should have been intercepted and dropped'); + const afterFirst = await localCollection.findOne(docId).exec(true); + assert.strictEqual(afterFirst.name, 'FirstUpdate'); + + // Restore original bulkWrite so meta works normally again. + metaInstance.bulkWrite = originalBulkWrite; + + // At this point the replication state is: + // forkState = { name: 'FirstUpdate', age: 2 } + // assumedMaster = { name: 'Initial', age: 1 } (stale - meta write was lost) + // + // Without the origin marker, downstream sees forkState != assumedMaster + // and treats it as a "non-upstream-replicated local write", skipping the document. + + // Update the document on remote again. + prevDown = internalState.streamQueue.down; + const remoteDoc2 = await remoteCollection.findOne(docId).exec(true); + await remoteDoc2.incrementalPatch({ + name: 'SecondUpdate', + age: 3 + }); + + // Wait for downstream to finish processing, then verify it recovered. + await waitUntil(() => internalState.streamQueue.down !== prevDown, undefined, 40); + await internalState.streamQueue.down; + + const localDoc = await localCollection.findOne(docId).exec(true); + assert.strictEqual(localDoc.name, 'SecondUpdate', 'should have replicated the second update from the remote'); + assert.strictEqual(localDoc.age, 3); + + await replicationState.cancel(); + await localCollection.database.destroy(); + await remoteCollection.database.destroy(); + }); + it('#7804 (2/2) should sync downstream updates when local and remote have different documents', async () => { + const { localCollection, remoteCollection } = await getTestCollections({ local: 0, remote: 0 }); + const docId = 'different-doc'; + + // Insert different documents in each + await remoteCollection.insert(schemaObjects.humanWithTimestampData({ + id: docId, + name: 'RemoteDocument', + age: 10 + })); + await localCollection.insert(schemaObjects.humanWithTimestampData({ + id: docId, + name: 'LocalDocument', + age: 20 + })); + + const replicationState = setupDownstreamTestReplication(localCollection, remoteCollection); + ensureReplicationHasNoErrors(replicationState); + + await replicationState.awaitInitialReplication(); + await replicationState.awaitInSync(); + + // Update document on remote + const internalState = ensureNotFalsy(replicationState.internalReplicationState); + const prevDown = internalState.streamQueue.down; + const remoteDoc = await remoteCollection.findOne(docId).exec(true); + await remoteDoc.incrementalPatch({ + name: 'UpdatedFromRemote', + age: 999 + }); + + // Wait for downstream cycle to complete + await waitUntil(() => internalState.streamQueue.down !== prevDown, 1000, 10); + await internalState.streamQueue.down; + + // Verify local received the update + const localDoc = await localCollection.findOne(docId).exec(true); + assert.strictEqual(localDoc.name, 'UpdatedFromRemote'); + assert.strictEqual(localDoc.age, 999); + + await replicationState.cancel(); + await localCollection.database.destroy(); + await remoteCollection.database.destroy(); + }); it('#4190 Composite Primary Keys broken on replicated collections', async () => { const db = await createRxDatabase({ name: randomCouchString(10), From 7bc18b2a48d7da08fa4c51576d43cfd8401352cb Mon Sep 17 00:00:00 2001 From: Artem Litchmanov Date: Thu, 20 Aug 2026 15:31:51 -0700 Subject: [PATCH 2/2] rebuild dist for the downstream origin marker port Co-Authored-By: Claude Fable 5 --- dist/cjs/replication-protocol/downstream.js | 20 ++++++++++++++++--- .../replication-protocol/downstream.js.map | 2 +- dist/cjs/types/rx-document.d.js.map | 2 +- dist/cjs/types/util.d.js.map | 2 +- dist/esm/replication-protocol/downstream.js | 20 ++++++++++++++++--- .../replication-protocol/downstream.js.map | 2 +- dist/esm/types/rx-document.d.js.map | 2 +- dist/esm/types/util.d.js.map | 2 +- dist/types/types/rx-document.d.ts | 12 ++++++++++- dist/types/types/util.d.ts | 9 ++++++++- 10 files changed, 59 insertions(+), 14 deletions(-) diff --git a/dist/cjs/replication-protocol/downstream.js b/dist/cjs/replication-protocol/downstream.js index 26fb440809e..5c7dd5cc11f 100644 --- a/dist/cjs/replication-protocol/downstream.js +++ b/dist/cjs/replication-protocol/downstream.js @@ -211,12 +211,15 @@ async function startReplicationDownstream(state) { if (!isAssumedMasterEqualToForkState && assumedMaster && assumedMaster.docData._rev && forkStateFullDoc && forkStateFullDoc._meta[state.input.identifier] && (0, _index.getHeightOfRevision)(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]) { isAssumedMasterEqualToForkState = true; } - if (forkStateFullDoc && assumedMaster && isAssumedMasterEqualToForkState === false || forkStateFullDoc && !assumedMaster) { + if ((forkStateFullDoc && assumedMaster && isAssumedMasterEqualToForkState === false || forkStateFullDoc && !assumedMaster) && !(forkStateFullDoc._meta.o && forkStateFullDoc._meta.o.hash === identifierHash && forkStateFullDoc._meta.o._rev === (0, _index.getHeightOfRevision)(forkStateFullDoc._rev))) { /** * We have a non-upstream-replicated * local write to the fork. - * This means we ignore the downstream of this document - * because anyway the upstream will first resolve the conflict. + * This means either we have to upstream the local + * doc data first, or it means that the fork state was + * synced from the master but the process exited before + * the metadata was written. + * @link https://github.com/pubkey/rxdb/pull/7804 */ return _index.PROMISE_RESOLVE_VOID; } @@ -272,6 +275,17 @@ async function startReplicationDownstream(state) { if (state.input.keepMeta && masterState._meta) { newForkState._meta = masterState._meta; } + + /** + * Tag the write with its origin so a later downstream run can tell + * "fork differs from assumed master" caused by a local write apart + * from one caused by a lost meta write. A local write bumps the + * revision height and voids the marker. + */ + newForkState._meta.o = { + _rev: !forkStateFullDoc ? 1 : (0, _index.getHeightOfRevision)(forkStateFullDoc._rev) + 1, + hash: identifierHash + }; var forkWriteRow = { previous: forkStateFullDoc, document: newForkState diff --git a/dist/cjs/replication-protocol/downstream.js.map b/dist/cjs/replication-protocol/downstream.js.map index 1cbd98e6b8f..db8ae83ba5d 100644 --- a/dist/cjs/replication-protocol/downstream.js.map +++ b/dist/cjs/replication-protocol/downstream.js.map @@ -1 +1 @@ -{"version":3,"file":"downstream.js","names":["_rxjs","require","_rxError","_rxStorageHelper","_index","_checkpoint","_helper","_metaInstance","startReplicationDownstream","state","input","initialCheckpoint","downstream","checkpointDoc","getLastCheckpointDoc","setCheckpoint","identifierHash","hashFunction","identifier","replicationHandler","timer","openTasks","addNewTask","task","stats","down","taskWithTime","time","push","streamQueue","then","useTasks","length","events","active","next","innerTaskWithTime","ensureNotFalsy","shift","lastTimeMasterChangesRequested","downstreamResyncOnce","downstreamProcessChanges","firstSyncDone","getValue","canceled","sub","masterChangeStream$","pipe","mergeMap","ev","firstValueFrom","up","filter","s","subscribe","masterChangeStreamEmit","unsubscribe","checkpointQueue","lastCheckpoint","promises","downResult","masterChangesSince","pullBatchSize","documents","stackCheckpoints","checkpoint","persistFromMaster","Promise","all","tasks","docsOfAllTasks","forEach","Error","appendToArray","persistenceQueue","PROMISE_RESOLVE_VOID","nonPersistedFromMaster","docs","primaryPath","docData","docId","downDocsById","useCheckpoint","docIds","Object","keys","writeRowsToFork","writeRowsToForkById","writeRowsToMeta","useMetaWriteRows","forkInstance","findDocumentsById","getAssumedMasterState","currentForkStateList","assumedMasterState","currentForkState","Map","doc","set","map","forkStateFullDoc","get","forkStateDocData","writeDocToDocState","hasAttachments","undefined","masterState","assumedMaster","metaDocument","isResolvedConflict","_rev","isAssumedMasterEqualToForkState","conflictHandler","realMasterState","newDocumentState","r","isEqual","_meta","getHeightOfRevision","areStatesExactlyEqual","getMetaWriteRow","newForkState","assign","flatClone","_attachments","getDefaultRevision","lwt","now","nextRevisionHeight","keepMeta","forkWriteRow","previous","document","createRevision","bulkWrite","downstreamBulkWriteFlag","forkWriteResult","success","processed","error","status","newRxError","writeError","metaInstance","stripAttachmentsDataFromMetaWriteRows","metaWriteResult","id","documentId","catch","unhandledError"],"sources":["../../../src/replication-protocol/downstream.ts"],"sourcesContent":["import {\n firstValueFrom,\n filter,\n mergeMap\n} from 'rxjs';\nimport { newRxError } from '../rx-error.ts';\nimport { stackCheckpoints } from '../rx-storage-helper.ts';\nimport type {\n RxStorageInstanceReplicationState,\n BulkWriteRow,\n BulkWriteRowById,\n RxStorageReplicationMeta,\n RxDocumentData,\n ById,\n WithDeleted,\n DocumentsWithCheckpoint,\n WithDeletedAndAttachments\n} from '../types/index.d.ts';\nimport {\n appendToArray,\n createRevision,\n ensureNotFalsy,\n flatClone,\n getDefaultRevision,\n getHeightOfRevision,\n now,\n PROMISE_RESOLVE_VOID\n} from '../plugins/utils/index.ts';\nimport {\n getLastCheckpointDoc,\n setCheckpoint\n} from './checkpoint.ts';\nimport {\n stripAttachmentsDataFromMetaWriteRows,\n writeDocToDocState\n} from './helper.ts';\nimport {\n getAssumedMasterState,\n getMetaWriteRow\n} from './meta-instance.ts';\n\n/**\n * Writes all documents from the master to the fork.\n * The downstream has two operation modes\n * - Sync by iterating over the checkpoints via downstreamResyncOnce()\n * - Sync by listening to the changestream via downstreamProcessChanges()\n * We need this to be able to do initial syncs\n * and still can have fast event based sync when the client is not offline.\n */\nexport async function startReplicationDownstream(\n state: RxStorageInstanceReplicationState\n) {\n if (\n state.input.initialCheckpoint &&\n state.input.initialCheckpoint.downstream\n ) {\n const checkpointDoc = await getLastCheckpointDoc(state, 'down');\n if (!checkpointDoc) {\n await setCheckpoint(\n state,\n 'down',\n state.input.initialCheckpoint.downstream\n );\n }\n }\n\n const identifierHash = await state.input.hashFunction(state.input.identifier);\n const replicationHandler = state.input.replicationHandler;\n\n // used to detect which tasks etc can in it at which order.\n let timer = 0;\n\n\n type Task = DocumentsWithCheckpoint | 'RESYNC';\n type TaskWithTime = {\n time: number;\n task: Task;\n };\n const openTasks: TaskWithTime[] = [];\n\n\n function addNewTask(task: Task): void {\n state.stats.down.addNewTask = state.stats.down.addNewTask + 1;\n const taskWithTime = {\n time: timer++,\n task\n };\n openTasks.push(taskWithTime);\n state.streamQueue.down = state.streamQueue.down\n .then(() => {\n const useTasks: Task[] = [];\n while (openTasks.length > 0) {\n state.events.active.down.next(true);\n const innerTaskWithTime = ensureNotFalsy(openTasks.shift());\n\n /**\n * If the task came in before the last time we started the pull\n * from the master, then we can drop the task.\n */\n if (innerTaskWithTime.time < lastTimeMasterChangesRequested) {\n continue;\n }\n\n if (innerTaskWithTime.task === 'RESYNC') {\n if (useTasks.length === 0) {\n useTasks.push(innerTaskWithTime.task);\n break;\n } else {\n break;\n }\n }\n\n useTasks.push(innerTaskWithTime.task);\n }\n if (useTasks.length === 0) {\n return;\n }\n\n if (useTasks[0] === 'RESYNC') {\n return downstreamResyncOnce();\n } else {\n return downstreamProcessChanges(useTasks);\n }\n }).then(() => {\n state.events.active.down.next(false);\n if (\n !state.firstSyncDone.down.getValue() &&\n !state.events.canceled.getValue()\n ) {\n state.firstSyncDone.down.next(true);\n }\n });\n }\n addNewTask('RESYNC');\n\n /**\n * If a write on the master happens, we have to trigger the downstream.\n * Only do this if not canceled yet, otherwise firstValueFrom errors\n * when running on a completed observable.\n */\n if (!state.events.canceled.getValue()) {\n const sub = replicationHandler\n .masterChangeStream$\n .pipe(\n mergeMap(async (ev) => {\n /**\n * While a push is running, we have to delay all incoming\n * events from the server to not mix up the replication state.\n */\n await firstValueFrom(\n state.events.active.up.pipe(filter(s => !s))\n );\n return ev;\n })\n )\n .subscribe((task: Task) => {\n state.stats.down.masterChangeStreamEmit = state.stats.down.masterChangeStreamEmit + 1;\n addNewTask(task);\n });\n firstValueFrom(\n state.events.canceled.pipe(\n filter(canceled => !!canceled)\n )\n ).then(() => sub.unsubscribe());\n }\n\n\n /**\n * For faster performance, we directly start each write\n * and then await all writes at the end.\n */\n let lastTimeMasterChangesRequested: number = -1;\n async function downstreamResyncOnce() {\n state.stats.down.downstreamResyncOnce = state.stats.down.downstreamResyncOnce + 1;\n if (state.events.canceled.getValue()) {\n return;\n }\n\n state.checkpointQueue = state.checkpointQueue.then(() => getLastCheckpointDoc(state, 'down'));\n let lastCheckpoint: CheckpointType = await state.checkpointQueue;\n\n\n const promises: Promise[] = [];\n while (!state.events.canceled.getValue()) {\n lastTimeMasterChangesRequested = timer++;\n const downResult = await replicationHandler.masterChangesSince(\n lastCheckpoint,\n state.input.pullBatchSize\n );\n\n if (downResult.documents.length === 0) {\n break;\n }\n\n lastCheckpoint = stackCheckpoints([lastCheckpoint, downResult.checkpoint]);\n\n promises.push(\n persistFromMaster(\n downResult.documents,\n lastCheckpoint\n )\n );\n\n /**\n * By definition we stop pull when the pulled documents\n * do not fill up the pullBatchSize because we\n * can assume that the remote has no more documents.\n */\n if (downResult.documents.length < state.input.pullBatchSize) {\n break;\n }\n\n }\n await Promise.all(promises);\n }\n\n\n function downstreamProcessChanges(tasks: Task[]) {\n state.stats.down.downstreamProcessChanges = state.stats.down.downstreamProcessChanges + 1;\n const docsOfAllTasks: WithDeleted[] = [];\n let lastCheckpoint: CheckpointType | undefined = null as any;\n\n tasks.forEach(task => {\n if (task === 'RESYNC') {\n throw new Error('SNH');\n }\n appendToArray(docsOfAllTasks, task.documents);\n lastCheckpoint = stackCheckpoints([lastCheckpoint, task.checkpoint]);\n });\n return persistFromMaster(\n docsOfAllTasks,\n ensureNotFalsy(lastCheckpoint)\n );\n }\n\n\n /**\n * It can happen that the calls to masterChangesSince() or the changeStream()\n * are way faster then how fast the documents can be persisted.\n * Therefore we merge all incoming downResults into the nonPersistedFromMaster object\n * and process them together if possible.\n * This often bundles up single writes and improves performance\n * by processing the documents in bulks.\n */\n let persistenceQueue = PROMISE_RESOLVE_VOID;\n const nonPersistedFromMaster: {\n checkpoint?: CheckpointType;\n docs: ById>;\n } = {\n docs: {}\n };\n\n function persistFromMaster(\n docs: WithDeleted[],\n checkpoint: CheckpointType\n ): Promise {\n const primaryPath = state.primaryPath;\n state.stats.down.persistFromMaster = state.stats.down.persistFromMaster + 1;\n\n /**\n * Add the new docs to the non-persistent list\n */\n docs.forEach(docData => {\n const docId: string = (docData as any)[primaryPath];\n nonPersistedFromMaster.docs[docId] = docData;\n });\n nonPersistedFromMaster.checkpoint = checkpoint;\n\n /**\n * Run in the queue\n * with all open documents from nonPersistedFromMaster.\n */\n persistenceQueue = persistenceQueue.then(() => {\n\n const downDocsById: ById> = nonPersistedFromMaster.docs;\n nonPersistedFromMaster.docs = {};\n const useCheckpoint = nonPersistedFromMaster.checkpoint;\n const docIds = Object.keys(downDocsById);\n\n if (\n state.events.canceled.getValue() ||\n docIds.length === 0\n ) {\n return PROMISE_RESOLVE_VOID;\n }\n\n const writeRowsToFork: BulkWriteRow[] = [];\n const writeRowsToForkById: ById> = {};\n const writeRowsToMeta: BulkWriteRowById> = {};\n const useMetaWriteRows: BulkWriteRow>[] = [];\n\n return Promise.all([\n state.input.forkInstance.findDocumentsById(docIds, true),\n getAssumedMasterState(\n state,\n docIds\n )\n ]).then(([\n currentForkStateList,\n assumedMasterState\n ]) => {\n const currentForkState = new Map>();\n currentForkStateList.forEach(doc => currentForkState.set((doc as any)[primaryPath], doc));\n return Promise.all(\n docIds.map(async (docId) => {\n const forkStateFullDoc: RxDocumentData | undefined = currentForkState.get(docId);\n const forkStateDocData: WithDeletedAndAttachments | undefined = forkStateFullDoc\n ? writeDocToDocState(forkStateFullDoc, state.hasAttachments, false)\n : undefined\n ;\n const masterState = downDocsById[docId];\n const assumedMaster = assumedMasterState[docId];\n\n if (\n assumedMaster &&\n forkStateFullDoc &&\n assumedMaster.metaDocument.isResolvedConflict === forkStateFullDoc._rev\n ) {\n /**\n * The current fork state represents a resolved conflict\n * that first must be send to the master in the upstream.\n * All conflicts are resolved by the upstream.\n */\n // return PROMISE_RESOLVE_VOID;\n await state.streamQueue.up;\n }\n\n let isAssumedMasterEqualToForkState = !assumedMaster || !forkStateDocData ?\n false :\n await state.input.conflictHandler({\n realMasterState: assumedMaster.docData,\n newDocumentState: forkStateDocData\n }, 'downstream-check-if-equal-0').then(r => r.isEqual);\n if (\n !isAssumedMasterEqualToForkState &&\n (\n assumedMaster &&\n (assumedMaster.docData as any)._rev &&\n forkStateFullDoc &&\n forkStateFullDoc._meta[state.input.identifier] &&\n getHeightOfRevision(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]\n )\n ) {\n isAssumedMasterEqualToForkState = true;\n }\n if (\n (\n forkStateFullDoc &&\n assumedMaster &&\n isAssumedMasterEqualToForkState === false\n ) ||\n (\n forkStateFullDoc && !assumedMaster\n )\n ) {\n /**\n * We have a non-upstream-replicated\n * local write to the fork.\n * This means we ignore the downstream of this document\n * because anyway the upstream will first resolve the conflict.\n */\n return PROMISE_RESOLVE_VOID;\n }\n\n const areStatesExactlyEqual = !forkStateDocData\n ? false\n : await state.input.conflictHandler(\n {\n realMasterState: masterState,\n newDocumentState: forkStateDocData\n },\n 'downstream-check-if-equal-1'\n ).then(r => r.isEqual);\n if (\n forkStateDocData &&\n areStatesExactlyEqual\n ) {\n /**\n * Document states are exactly equal.\n * This can happen when the replication is shut down\n * unexpected like when the user goes offline.\n *\n * Only when the assumedMaster is different from the forkState,\n * we have to patch the document in the meta instance.\n */\n if (\n !assumedMaster ||\n isAssumedMasterEqualToForkState === false\n ) {\n useMetaWriteRows.push(\n await getMetaWriteRow(\n state,\n forkStateDocData,\n assumedMaster ? assumedMaster.metaDocument : undefined\n )\n );\n }\n return PROMISE_RESOLVE_VOID;\n }\n\n /**\n * All other master states need to be written to the forkInstance\n * and metaInstance.\n */\n const newForkState = Object.assign(\n {},\n masterState,\n forkStateFullDoc ? {\n _meta: flatClone(forkStateFullDoc._meta),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {},\n _rev: getDefaultRevision()\n } : {\n _meta: {\n lwt: now()\n },\n _rev: getDefaultRevision(),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {}\n }\n );\n /**\n * If the remote works with revisions,\n * we store the height of the next fork-state revision\n * inside of the documents meta data.\n * By doing so we can filter it out in the upstream\n * and detect the document as being equal to master or not.\n * This is used for example in the CouchDB replication plugin.\n */\n if ((masterState as any)._rev) {\n const nextRevisionHeight = !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1;\n newForkState._meta[state.input.identifier] = nextRevisionHeight;\n if (state.input.keepMeta) {\n newForkState._rev = (masterState as any)._rev;\n }\n }\n if (\n state.input.keepMeta &&\n (masterState as any)._meta\n ) {\n newForkState._meta = (masterState as any)._meta;\n }\n\n const forkWriteRow = {\n previous: forkStateFullDoc,\n document: newForkState\n };\n\n forkWriteRow.document._rev = forkWriteRow.document._rev ? forkWriteRow.document._rev : createRevision(\n identifierHash,\n forkWriteRow.previous\n );\n writeRowsToFork.push(forkWriteRow);\n writeRowsToForkById[docId] = forkWriteRow;\n writeRowsToMeta[docId] = await getMetaWriteRow(\n state,\n masterState,\n assumedMaster ? assumedMaster.metaDocument : undefined\n );\n })\n );\n }).then(async () => {\n if (writeRowsToFork.length > 0) {\n return state.input.forkInstance.bulkWrite(\n writeRowsToFork,\n await state.downstreamBulkWriteFlag\n ).then((forkWriteResult) => {\n forkWriteResult.success.forEach(doc => {\n const docId = (doc as any)[primaryPath];\n state.events.processed.down.next(writeRowsToForkById[docId]);\n useMetaWriteRows.push(writeRowsToMeta[docId]);\n });\n forkWriteResult.error.forEach(error => {\n /**\n * We do not have to care about downstream conflict errors here\n * because on conflict, it will be solved locally and result in another write.\n */\n if (error.status === 409) {\n return;\n }\n // other non-conflict errors must be handled\n state.events.error.next(newRxError('RC_PULL', {\n writeError: error\n }));\n });\n });\n }\n }).then(() => {\n if (useMetaWriteRows.length > 0) {\n return state.input.metaInstance.bulkWrite(\n stripAttachmentsDataFromMetaWriteRows(state, useMetaWriteRows),\n 'replication-down-write-meta'\n ).then(metaWriteResult => {\n metaWriteResult.error\n .forEach(writeError => {\n state.events.error.next(newRxError('RC_PULL', {\n id: writeError.documentId,\n writeError\n }));\n });\n });\n }\n }).then(() => {\n /**\n * For better performance we do not await checkpoint writes,\n * but to ensure order on parallel checkpoint writes,\n * we have to use a queue.\n */\n setCheckpoint(\n state,\n 'down',\n useCheckpoint\n );\n });\n }).catch(unhandledError => state.events.error.next(unhandledError));\n return persistenceQueue;\n }\n}\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"downstream.js","names":["_rxjs","require","_rxError","_rxStorageHelper","_index","_checkpoint","_helper","_metaInstance","startReplicationDownstream","state","input","initialCheckpoint","downstream","checkpointDoc","getLastCheckpointDoc","setCheckpoint","identifierHash","hashFunction","identifier","replicationHandler","timer","openTasks","addNewTask","task","stats","down","taskWithTime","time","push","streamQueue","then","useTasks","length","events","active","next","innerTaskWithTime","ensureNotFalsy","shift","lastTimeMasterChangesRequested","downstreamResyncOnce","downstreamProcessChanges","firstSyncDone","getValue","canceled","sub","masterChangeStream$","pipe","mergeMap","ev","firstValueFrom","up","filter","s","subscribe","masterChangeStreamEmit","unsubscribe","checkpointQueue","lastCheckpoint","promises","downResult","masterChangesSince","pullBatchSize","documents","stackCheckpoints","checkpoint","persistFromMaster","Promise","all","tasks","docsOfAllTasks","forEach","Error","appendToArray","persistenceQueue","PROMISE_RESOLVE_VOID","nonPersistedFromMaster","docs","primaryPath","docData","docId","downDocsById","useCheckpoint","docIds","Object","keys","writeRowsToFork","writeRowsToForkById","writeRowsToMeta","useMetaWriteRows","forkInstance","findDocumentsById","getAssumedMasterState","currentForkStateList","assumedMasterState","currentForkState","Map","doc","set","map","forkStateFullDoc","get","forkStateDocData","writeDocToDocState","hasAttachments","undefined","masterState","assumedMaster","metaDocument","isResolvedConflict","_rev","isAssumedMasterEqualToForkState","conflictHandler","realMasterState","newDocumentState","r","isEqual","_meta","getHeightOfRevision","o","hash","areStatesExactlyEqual","getMetaWriteRow","newForkState","assign","flatClone","_attachments","getDefaultRevision","lwt","now","nextRevisionHeight","keepMeta","forkWriteRow","previous","document","createRevision","bulkWrite","downstreamBulkWriteFlag","forkWriteResult","success","processed","error","status","newRxError","writeError","metaInstance","stripAttachmentsDataFromMetaWriteRows","metaWriteResult","id","documentId","catch","unhandledError"],"sources":["../../../src/replication-protocol/downstream.ts"],"sourcesContent":["import {\n firstValueFrom,\n filter,\n mergeMap\n} from 'rxjs';\nimport { newRxError } from '../rx-error.ts';\nimport { stackCheckpoints } from '../rx-storage-helper.ts';\nimport type {\n RxStorageInstanceReplicationState,\n BulkWriteRow,\n BulkWriteRowById,\n RxStorageReplicationMeta,\n RxDocumentData,\n ById,\n WithDeleted,\n DocumentsWithCheckpoint,\n WithDeletedAndAttachments\n} from '../types/index.d.ts';\nimport {\n appendToArray,\n createRevision,\n ensureNotFalsy,\n flatClone,\n getDefaultRevision,\n getHeightOfRevision,\n now,\n PROMISE_RESOLVE_VOID\n} from '../plugins/utils/index.ts';\nimport {\n getLastCheckpointDoc,\n setCheckpoint\n} from './checkpoint.ts';\nimport {\n stripAttachmentsDataFromMetaWriteRows,\n writeDocToDocState\n} from './helper.ts';\nimport {\n getAssumedMasterState,\n getMetaWriteRow\n} from './meta-instance.ts';\n\n/**\n * Writes all documents from the master to the fork.\n * The downstream has two operation modes\n * - Sync by iterating over the checkpoints via downstreamResyncOnce()\n * - Sync by listening to the changestream via downstreamProcessChanges()\n * We need this to be able to do initial syncs\n * and still can have fast event based sync when the client is not offline.\n */\nexport async function startReplicationDownstream(\n state: RxStorageInstanceReplicationState\n) {\n if (\n state.input.initialCheckpoint &&\n state.input.initialCheckpoint.downstream\n ) {\n const checkpointDoc = await getLastCheckpointDoc(state, 'down');\n if (!checkpointDoc) {\n await setCheckpoint(\n state,\n 'down',\n state.input.initialCheckpoint.downstream\n );\n }\n }\n\n const identifierHash = await state.input.hashFunction(state.input.identifier);\n const replicationHandler = state.input.replicationHandler;\n\n // used to detect which tasks etc can in it at which order.\n let timer = 0;\n\n\n type Task = DocumentsWithCheckpoint | 'RESYNC';\n type TaskWithTime = {\n time: number;\n task: Task;\n };\n const openTasks: TaskWithTime[] = [];\n\n\n function addNewTask(task: Task): void {\n state.stats.down.addNewTask = state.stats.down.addNewTask + 1;\n const taskWithTime = {\n time: timer++,\n task\n };\n openTasks.push(taskWithTime);\n state.streamQueue.down = state.streamQueue.down\n .then(() => {\n const useTasks: Task[] = [];\n while (openTasks.length > 0) {\n state.events.active.down.next(true);\n const innerTaskWithTime = ensureNotFalsy(openTasks.shift());\n\n /**\n * If the task came in before the last time we started the pull\n * from the master, then we can drop the task.\n */\n if (innerTaskWithTime.time < lastTimeMasterChangesRequested) {\n continue;\n }\n\n if (innerTaskWithTime.task === 'RESYNC') {\n if (useTasks.length === 0) {\n useTasks.push(innerTaskWithTime.task);\n break;\n } else {\n break;\n }\n }\n\n useTasks.push(innerTaskWithTime.task);\n }\n if (useTasks.length === 0) {\n return;\n }\n\n if (useTasks[0] === 'RESYNC') {\n return downstreamResyncOnce();\n } else {\n return downstreamProcessChanges(useTasks);\n }\n }).then(() => {\n state.events.active.down.next(false);\n if (\n !state.firstSyncDone.down.getValue() &&\n !state.events.canceled.getValue()\n ) {\n state.firstSyncDone.down.next(true);\n }\n });\n }\n addNewTask('RESYNC');\n\n /**\n * If a write on the master happens, we have to trigger the downstream.\n * Only do this if not canceled yet, otherwise firstValueFrom errors\n * when running on a completed observable.\n */\n if (!state.events.canceled.getValue()) {\n const sub = replicationHandler\n .masterChangeStream$\n .pipe(\n mergeMap(async (ev) => {\n /**\n * While a push is running, we have to delay all incoming\n * events from the server to not mix up the replication state.\n */\n await firstValueFrom(\n state.events.active.up.pipe(filter(s => !s))\n );\n return ev;\n })\n )\n .subscribe((task: Task) => {\n state.stats.down.masterChangeStreamEmit = state.stats.down.masterChangeStreamEmit + 1;\n addNewTask(task);\n });\n firstValueFrom(\n state.events.canceled.pipe(\n filter(canceled => !!canceled)\n )\n ).then(() => sub.unsubscribe());\n }\n\n\n /**\n * For faster performance, we directly start each write\n * and then await all writes at the end.\n */\n let lastTimeMasterChangesRequested: number = -1;\n async function downstreamResyncOnce() {\n state.stats.down.downstreamResyncOnce = state.stats.down.downstreamResyncOnce + 1;\n if (state.events.canceled.getValue()) {\n return;\n }\n\n state.checkpointQueue = state.checkpointQueue.then(() => getLastCheckpointDoc(state, 'down'));\n let lastCheckpoint: CheckpointType = await state.checkpointQueue;\n\n\n const promises: Promise[] = [];\n while (!state.events.canceled.getValue()) {\n lastTimeMasterChangesRequested = timer++;\n const downResult = await replicationHandler.masterChangesSince(\n lastCheckpoint,\n state.input.pullBatchSize\n );\n\n if (downResult.documents.length === 0) {\n break;\n }\n\n lastCheckpoint = stackCheckpoints([lastCheckpoint, downResult.checkpoint]);\n\n promises.push(\n persistFromMaster(\n downResult.documents,\n lastCheckpoint\n )\n );\n\n /**\n * By definition we stop pull when the pulled documents\n * do not fill up the pullBatchSize because we\n * can assume that the remote has no more documents.\n */\n if (downResult.documents.length < state.input.pullBatchSize) {\n break;\n }\n\n }\n await Promise.all(promises);\n }\n\n\n function downstreamProcessChanges(tasks: Task[]) {\n state.stats.down.downstreamProcessChanges = state.stats.down.downstreamProcessChanges + 1;\n const docsOfAllTasks: WithDeleted[] = [];\n let lastCheckpoint: CheckpointType | undefined = null as any;\n\n tasks.forEach(task => {\n if (task === 'RESYNC') {\n throw new Error('SNH');\n }\n appendToArray(docsOfAllTasks, task.documents);\n lastCheckpoint = stackCheckpoints([lastCheckpoint, task.checkpoint]);\n });\n return persistFromMaster(\n docsOfAllTasks,\n ensureNotFalsy(lastCheckpoint)\n );\n }\n\n\n /**\n * It can happen that the calls to masterChangesSince() or the changeStream()\n * are way faster then how fast the documents can be persisted.\n * Therefore we merge all incoming downResults into the nonPersistedFromMaster object\n * and process them together if possible.\n * This often bundles up single writes and improves performance\n * by processing the documents in bulks.\n */\n let persistenceQueue = PROMISE_RESOLVE_VOID;\n const nonPersistedFromMaster: {\n checkpoint?: CheckpointType;\n docs: ById>;\n } = {\n docs: {}\n };\n\n function persistFromMaster(\n docs: WithDeleted[],\n checkpoint: CheckpointType\n ): Promise {\n const primaryPath = state.primaryPath;\n state.stats.down.persistFromMaster = state.stats.down.persistFromMaster + 1;\n\n /**\n * Add the new docs to the non-persistent list\n */\n docs.forEach(docData => {\n const docId: string = (docData as any)[primaryPath];\n nonPersistedFromMaster.docs[docId] = docData;\n });\n nonPersistedFromMaster.checkpoint = checkpoint;\n\n /**\n * Run in the queue\n * with all open documents from nonPersistedFromMaster.\n */\n persistenceQueue = persistenceQueue.then(() => {\n\n const downDocsById: ById> = nonPersistedFromMaster.docs;\n nonPersistedFromMaster.docs = {};\n const useCheckpoint = nonPersistedFromMaster.checkpoint;\n const docIds = Object.keys(downDocsById);\n\n if (\n state.events.canceled.getValue() ||\n docIds.length === 0\n ) {\n return PROMISE_RESOLVE_VOID;\n }\n\n const writeRowsToFork: BulkWriteRow[] = [];\n const writeRowsToForkById: ById> = {};\n const writeRowsToMeta: BulkWriteRowById> = {};\n const useMetaWriteRows: BulkWriteRow>[] = [];\n\n return Promise.all([\n state.input.forkInstance.findDocumentsById(docIds, true),\n getAssumedMasterState(\n state,\n docIds\n )\n ]).then(([\n currentForkStateList,\n assumedMasterState\n ]) => {\n const currentForkState = new Map>();\n currentForkStateList.forEach(doc => currentForkState.set((doc as any)[primaryPath], doc));\n return Promise.all(\n docIds.map(async (docId) => {\n const forkStateFullDoc: RxDocumentData | undefined = currentForkState.get(docId);\n const forkStateDocData: WithDeletedAndAttachments | undefined = forkStateFullDoc\n ? writeDocToDocState(forkStateFullDoc, state.hasAttachments, false)\n : undefined\n ;\n const masterState = downDocsById[docId];\n const assumedMaster = assumedMasterState[docId];\n\n if (\n assumedMaster &&\n forkStateFullDoc &&\n assumedMaster.metaDocument.isResolvedConflict === forkStateFullDoc._rev\n ) {\n /**\n * The current fork state represents a resolved conflict\n * that first must be send to the master in the upstream.\n * All conflicts are resolved by the upstream.\n */\n // return PROMISE_RESOLVE_VOID;\n await state.streamQueue.up;\n }\n\n let isAssumedMasterEqualToForkState = !assumedMaster || !forkStateDocData ?\n false :\n await state.input.conflictHandler({\n realMasterState: assumedMaster.docData,\n newDocumentState: forkStateDocData\n }, 'downstream-check-if-equal-0').then(r => r.isEqual);\n if (\n !isAssumedMasterEqualToForkState &&\n (\n assumedMaster &&\n (assumedMaster.docData as any)._rev &&\n forkStateFullDoc &&\n forkStateFullDoc._meta[state.input.identifier] &&\n getHeightOfRevision(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]\n )\n ) {\n isAssumedMasterEqualToForkState = true;\n }\n if (\n (\n (\n forkStateFullDoc &&\n assumedMaster &&\n isAssumedMasterEqualToForkState === false\n ) ||\n (\n forkStateFullDoc && !assumedMaster\n )\n ) &&\n !(\n forkStateFullDoc._meta.o &&\n (\n forkStateFullDoc._meta.o.hash === identifierHash &&\n forkStateFullDoc._meta.o._rev === getHeightOfRevision(forkStateFullDoc._rev)\n )\n )\n ) {\n /**\n * We have a non-upstream-replicated\n * local write to the fork.\n * This means either we have to upstream the local\n * doc data first, or it means that the fork state was\n * synced from the master but the process exited before\n * the metadata was written.\n * @link https://github.com/pubkey/rxdb/pull/7804\n */\n return PROMISE_RESOLVE_VOID;\n }\n\n const areStatesExactlyEqual = !forkStateDocData\n ? false\n : await state.input.conflictHandler(\n {\n realMasterState: masterState,\n newDocumentState: forkStateDocData\n },\n 'downstream-check-if-equal-1'\n ).then(r => r.isEqual);\n if (\n forkStateDocData &&\n areStatesExactlyEqual\n ) {\n /**\n * Document states are exactly equal.\n * This can happen when the replication is shut down\n * unexpected like when the user goes offline.\n *\n * Only when the assumedMaster is different from the forkState,\n * we have to patch the document in the meta instance.\n */\n if (\n !assumedMaster ||\n isAssumedMasterEqualToForkState === false\n ) {\n useMetaWriteRows.push(\n await getMetaWriteRow(\n state,\n forkStateDocData,\n assumedMaster ? assumedMaster.metaDocument : undefined\n )\n );\n }\n return PROMISE_RESOLVE_VOID;\n }\n\n /**\n * All other master states need to be written to the forkInstance\n * and metaInstance.\n */\n const newForkState = Object.assign(\n {},\n masterState,\n forkStateFullDoc ? {\n _meta: flatClone(forkStateFullDoc._meta),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {},\n _rev: getDefaultRevision()\n } : {\n _meta: {\n lwt: now()\n },\n _rev: getDefaultRevision(),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {}\n }\n );\n /**\n * If the remote works with revisions,\n * we store the height of the next fork-state revision\n * inside of the documents meta data.\n * By doing so we can filter it out in the upstream\n * and detect the document as being equal to master or not.\n * This is used for example in the CouchDB replication plugin.\n */\n if ((masterState as any)._rev) {\n const nextRevisionHeight = !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1;\n newForkState._meta[state.input.identifier] = nextRevisionHeight;\n if (state.input.keepMeta) {\n newForkState._rev = (masterState as any)._rev;\n }\n }\n if (\n state.input.keepMeta &&\n (masterState as any)._meta\n ) {\n newForkState._meta = (masterState as any)._meta;\n }\n\n /**\n * Tag the write with its origin so a later downstream run can tell\n * \"fork differs from assumed master\" caused by a local write apart\n * from one caused by a lost meta write. A local write bumps the\n * revision height and voids the marker.\n */\n newForkState._meta.o = {\n _rev: !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1,\n hash: identifierHash\n };\n\n const forkWriteRow = {\n previous: forkStateFullDoc,\n document: newForkState\n };\n\n forkWriteRow.document._rev = forkWriteRow.document._rev ? forkWriteRow.document._rev : createRevision(\n identifierHash,\n forkWriteRow.previous\n );\n writeRowsToFork.push(forkWriteRow);\n writeRowsToForkById[docId] = forkWriteRow;\n writeRowsToMeta[docId] = await getMetaWriteRow(\n state,\n masterState,\n assumedMaster ? assumedMaster.metaDocument : undefined\n );\n })\n );\n }).then(async () => {\n if (writeRowsToFork.length > 0) {\n return state.input.forkInstance.bulkWrite(\n writeRowsToFork,\n await state.downstreamBulkWriteFlag\n ).then((forkWriteResult) => {\n forkWriteResult.success.forEach(doc => {\n const docId = (doc as any)[primaryPath];\n state.events.processed.down.next(writeRowsToForkById[docId]);\n useMetaWriteRows.push(writeRowsToMeta[docId]);\n });\n forkWriteResult.error.forEach(error => {\n /**\n * We do not have to care about downstream conflict errors here\n * because on conflict, it will be solved locally and result in another write.\n */\n if (error.status === 409) {\n return;\n }\n // other non-conflict errors must be handled\n state.events.error.next(newRxError('RC_PULL', {\n writeError: error\n }));\n });\n });\n }\n }).then(() => {\n if (useMetaWriteRows.length > 0) {\n return state.input.metaInstance.bulkWrite(\n stripAttachmentsDataFromMetaWriteRows(state, useMetaWriteRows),\n 'replication-down-write-meta'\n ).then(metaWriteResult => {\n metaWriteResult.error\n .forEach(writeError => {\n state.events.error.next(newRxError('RC_PULL', {\n id: writeError.documentId,\n writeError\n }));\n });\n });\n }\n }).then(() => {\n /**\n * For better performance we do not await checkpoint writes,\n * but to ensure order on parallel checkpoint writes,\n * we have to use a queue.\n */\n setCheckpoint(\n state,\n 'down',\n useCheckpoint\n );\n });\n }).catch(unhandledError => state.events.error.next(unhandledError));\n return persistenceQueue;\n }\n}\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file diff --git a/dist/cjs/types/rx-document.d.js.map b/dist/cjs/types/rx-document.d.js.map index eb6baf2addd..c5a9e8f8a60 100644 --- a/dist/cjs/types/rx-document.d.js.map +++ b/dist/cjs/types/rx-document.d.js.map @@ -1 +1 @@ -{"version":3,"file":"rx-document.d.js","names":[],"sources":["../../../src/types/rx-document.d.ts"],"sourcesContent":["import {\n Observable\n} from 'rxjs';\n\nimport type {\n RxCollection,\n} from './rx-collection.d.ts';\nimport type {\n RxAttachment,\n RxAttachmentCreator\n} from './rx-attachment.d.ts';\nimport type { RxDocumentData, WithDeleted } from './rx-storage.d.ts';\nimport type { RxChangeEvent } from './rx-change-event.d.ts';\nimport type { DeepReadonly, MaybePromise, PlainJsonValue } from './util.d.ts';\nimport type { UpdateQuery } from './plugins/update.d.ts';\nimport type { CRDTEntry } from './plugins/crdt.d.ts';\n\n\n\nexport type RxDocument = RxDocumentBase<\n RxDocumentType,\n OrmMethods,\n Reactivity\n> & RxDocumentType & OrmMethods & ExtendObservables & ExtendReactivity;\n\n\n/**\n * Extend the base properties by the property$ fields\n * so it knows that RxDocument.age also has RxDocument.age$ which is\n * an observable.\n * TODO how to do this for the nested fields?\n */\ntype ExtendObservables = {\n [P in keyof RxDocumentType as `${string & P}$`]: Observable;\n};\n\ntype ExtendReactivity = {\n [P in keyof RxDocumentType as `${string & P}$$`]: Reactivity;\n};\n\n/**\n * The public facing modify update function.\n * It only gets the document parts as input, that\n * are mutateable by the user.\n */\nexport type ModifyFunction = (\n doc: WithDeleted\n) => MaybePromise> | MaybePromise;\n\n/**\n * Meta data that is attached to each document by RxDB.\n */\nexport type RxDocumentMeta = {\n /**\n * Last write time.\n * Unix epoch in milliseconds.\n */\n lwt: number;\n\n /**\n * Any other value can be attached to the _meta data.\n * Mostly done by plugins to mark documents.\n */\n [k: string]: PlainJsonValue;\n};\n\nexport declare interface RxDocumentBase {\n isInstanceOfRxDocument: true;\n collection: RxCollection;\n readonly deleted: boolean;\n\n readonly $: Observable>;\n readonly $$: Reactivity;\n readonly deleted$: Observable;\n readonly deleted$$: Reactivity;\n\n readonly primary: string;\n readonly allAttachments$: Observable[]>;\n\n // internal things\n _data: RxDocumentData;\n primaryPath: string;\n revision: string;\n /**\n * Used to de-duplicate the enriched property objects\n * of the document.\n */\n _propertyCache: Map;\n $emit(cE: RxChangeEvent): void;\n _saveData(newData: any, oldData: any): Promise>;\n // /internal things\n\n // Returns the latest state of the document\n getLatest(): RxDocument;\n\n\n get$(path: string): Observable;\n get$$(path: string): Reactivity;\n get(objPath: string): DeepReadonly;\n populate(objPath: string): Promise | any | null>;\n\n /**\n * mutate the document with a function\n */\n modify(mutationFunction: ModifyFunction, context?: string): Promise>;\n incrementalModify(mutationFunction: ModifyFunction, context?: string): Promise>;\n\n /**\n * patches the given properties\n */\n patch(patch: Partial): Promise>;\n incrementalPatch(patch: Partial): Promise>;\n\n update(updateObj: UpdateQuery): Promise>;\n incrementalUpdate(updateObj: UpdateQuery): Promise>;\n\n updateCRDT(updateObj: CRDTEntry | CRDTEntry[]): Promise>;\n\n remove(): Promise>;\n incrementalRemove(): Promise>;\n\n // only for temporary documents\n set(objPath: string, value: any): RxDocument;\n save(): Promise;\n\n // attachments\n putAttachment(\n creator: RxAttachmentCreator\n ): Promise>;\n getAttachment(id: string): RxAttachment | null;\n allAttachments(): RxAttachment[];\n\n toJSON(withRevAndAttachments: true): DeepReadonly>;\n toJSON(withRevAndAttachments?: false): DeepReadonly;\n\n toMutableJSON(withRevAndAttachments: true): RxDocumentData;\n toMutableJSON(withRevAndAttachments?: false): RxDocType;\n\n destroy(): void;\n}\n"],"mappings":"","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"rx-document.d.js","names":[],"sources":["../../../src/types/rx-document.d.ts"],"sourcesContent":["import {\n Observable\n} from 'rxjs';\n\nimport type {\n RxCollection,\n} from './rx-collection.d.ts';\nimport type {\n RxAttachment,\n RxAttachmentCreator\n} from './rx-attachment.d.ts';\nimport type { RxDocumentData, WithDeleted } from './rx-storage.d.ts';\nimport type { RxChangeEvent } from './rx-change-event.d.ts';\nimport type { DeepReadonly, MaybePromise, PlainJsonValue } from './util.d.ts';\nimport type { UpdateQuery } from './plugins/update.d.ts';\nimport type { CRDTEntry } from './plugins/crdt.d.ts';\n\n\n\nexport type RxDocument = RxDocumentBase<\n RxDocumentType,\n OrmMethods,\n Reactivity\n> & RxDocumentType & OrmMethods & ExtendObservables & ExtendReactivity;\n\n\n/**\n * Extend the base properties by the property$ fields\n * so it knows that RxDocument.age also has RxDocument.age$ which is\n * an observable.\n * TODO how to do this for the nested fields?\n */\ntype ExtendObservables = {\n [P in keyof RxDocumentType as `${string & P}$`]: Observable;\n};\n\ntype ExtendReactivity = {\n [P in keyof RxDocumentType as `${string & P}$$`]: Reactivity;\n};\n\n/**\n * The public facing modify update function.\n * It only gets the document parts as input, that\n * are mutateable by the user.\n */\nexport type ModifyFunction = (\n doc: WithDeleted\n) => MaybePromise> | MaybePromise;\n\n/**\n * Meta data that is attached to each document by RxDB.\n */\nexport type RxDocumentMeta = {\n /**\n * Last write time.\n * Unix epoch in milliseconds.\n */\n lwt: number;\n\n /**\n * The replication plugins \"tags\" the origin\n * of writes to later know if a write came from\n * the replication or was done locally.\n */\n o?: {\n hash: string;\n _rev: number;\n };\n\n /**\n * Any other value can be attached to the _meta data.\n * Mostly done by plugins to mark documents.\n */\n [k: string]: PlainJsonValue | undefined;\n};\n\nexport declare interface RxDocumentBase {\n isInstanceOfRxDocument: true;\n collection: RxCollection;\n readonly deleted: boolean;\n\n readonly $: Observable>;\n readonly $$: Reactivity;\n readonly deleted$: Observable;\n readonly deleted$$: Reactivity;\n\n readonly primary: string;\n readonly allAttachments$: Observable[]>;\n\n // internal things\n _data: RxDocumentData;\n primaryPath: string;\n revision: string;\n /**\n * Used to de-duplicate the enriched property objects\n * of the document.\n */\n _propertyCache: Map;\n $emit(cE: RxChangeEvent): void;\n _saveData(newData: any, oldData: any): Promise>;\n // /internal things\n\n // Returns the latest state of the document\n getLatest(): RxDocument;\n\n\n get$(path: string): Observable;\n get$$(path: string): Reactivity;\n get(objPath: string): DeepReadonly;\n populate(objPath: string): Promise | any | null>;\n\n /**\n * mutate the document with a function\n */\n modify(mutationFunction: ModifyFunction, context?: string): Promise>;\n incrementalModify(mutationFunction: ModifyFunction, context?: string): Promise>;\n\n /**\n * patches the given properties\n */\n patch(patch: Partial): Promise>;\n incrementalPatch(patch: Partial): Promise>;\n\n update(updateObj: UpdateQuery): Promise>;\n incrementalUpdate(updateObj: UpdateQuery): Promise>;\n\n updateCRDT(updateObj: CRDTEntry | CRDTEntry[]): Promise>;\n\n remove(): Promise>;\n incrementalRemove(): Promise>;\n\n // only for temporary documents\n set(objPath: string, value: any): RxDocument;\n save(): Promise;\n\n // attachments\n putAttachment(\n creator: RxAttachmentCreator\n ): Promise>;\n getAttachment(id: string): RxAttachment | null;\n allAttachments(): RxAttachment[];\n\n toJSON(withRevAndAttachments: true): DeepReadonly>;\n toJSON(withRevAndAttachments?: false): DeepReadonly;\n\n toMutableJSON(withRevAndAttachments: true): RxDocumentData;\n toMutableJSON(withRevAndAttachments?: false): RxDocType;\n\n destroy(): void;\n}\n"],"mappings":"","ignoreList":[]} \ No newline at end of file diff --git a/dist/cjs/types/util.d.js.map b/dist/cjs/types/util.d.js.map index 9d1b26e0974..08295e33e92 100644 --- a/dist/cjs/types/util.d.js.map +++ b/dist/cjs/types/util.d.js.map @@ -1 +1 @@ -{"version":3,"file":"util.d.js","names":[],"sources":["../../../src/types/util.d.ts"],"sourcesContent":["import type { RxStorage } from './rx-storage.interface';\n\nexport type MaybePromise = Promise | T;\n\n\nexport type PlainJsonValue = string | number | boolean | PlainSimpleJsonObject | PlainSimpleJsonObject[] | PlainJsonValue[];\nexport type PlainSimpleJsonObject = {\n [k: string]: PlainJsonValue | PlainJsonValue[];\n};\n\n/**\n * @link https://stackoverflow.com/a/49670389/3443137\n */\ntype DeepReadonly =\n T extends (infer R)[] ? DeepReadonlyArray :\n T extends Function ? T :\n T extends object ? DeepReadonlyObject :\n T;\n\ninterface DeepReadonlyArray extends ReadonlyArray> { }\n\ntype DeepReadonlyObject = {\n readonly [P in keyof T]: DeepReadonly;\n};\n\nexport type MaybeReadonly = T | Readonly;\n\n\n/**\n * Opposite of DeepReadonly,\n * makes everything mutable again.\n */\ntype DeepMutable = (\n T extends object\n ? {\n -readonly [K in keyof T]: (\n T[K] extends object\n ? DeepMutable\n : T[K]\n )\n }\n : never\n);\n\n/**\n * Can be used like 'keyof'\n * but only represents the string keys, not the Symbols or numbers.\n * @link https://stackoverflow.com/a/51808262/3443137\n */\nexport type StringKeys = Extract;\n\nexport type AnyKeys = { [P in keyof T]?: T[P] | any };\nexport interface AnyObject {\n [k: string]: any;\n}\n\n/**\n * @link https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l\n */\nexport type Override = Omit & T2;\n\n\n\nexport type ById = {\n [id: string]: T;\n};\n\n/**\n * Must be async to support async hashing like from the WebCrypto API.\n */\nexport type HashFunction = (input: string) => Promise;\n\nexport declare type QueryMatcher = (doc: DocType | DeepReadonly) => boolean;\n\n/**\n * To have a deterministic sorting, we cannot return 0,\n * we only return 1 or -1.\n * This ensures that we always end with the same output array, no mather of the\n * pre-sorting of the input array.\n */\nexport declare type DeterministicSortComparator = (a: DocType, b: DocType) => 1 | -1;\n\n/**\n * To test a storage, we need these\n * configuration values.\n */\nexport type RxTestStorage = {\n // can be used to setup async stuff\n readonly init?: () => any;\n // TODO remove name here, it can be read out already via getStorage().name\n readonly name: string;\n readonly getStorage: () => RxStorage;\n /**\n * Returns a storage that is used in performance tests.\n * For example in a browser it should return the storage with an IndexedDB based adapter,\n * while in node.js it must use the filesystem.\n */\n readonly getPerformanceStorage: () => {\n storage: RxStorage;\n /**\n * A description that describes the storage and setting.\n * For example 'dexie-native'.\n */\n description: string;\n };\n /**\n * True if the storage is able to\n * keep data after an instance is closed and opened again.\n */\n readonly hasPersistence: boolean;\n readonly hasMultiInstance: boolean;\n readonly hasAttachments: boolean;\n\n /**\n * Some storages likes the memory-synced storage,\n * are not able to provide a replication while guaranteeing\n * data integrity.\n */\n readonly hasReplication: boolean;\n\n /**\n * To make it possible to test alternative encryption plugins,\n * you can specify hasEncryption to signal\n * the test runner that the given storage already contains an\n * encryption plugin that should be used to test encryption tests.\n * Otherwise the encryption-crypto-js plugin will be tested.\n *\n * hasEncryption must contain a function that is able\n * to create a new password.\n */\n readonly hasEncryption?: () => Promise;\n};\n\n\n/**\n * The paths as strings-type of nested object\n * @link https://stackoverflow.com/a/58436959/3443137\n */\ntype Join = K extends string | number ?\n P extends string | number ?\n `${K}${'' extends P ? '' : '.'}${P}`\n : never : never;\n\nexport type Paths = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: K extends string | number ?\n `${K}` | (Paths extends infer R ? Join : never)\n : never\n }[keyof T] : '';\n\nexport type Leaves = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: Join> }[keyof T] : '';\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\n 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n"],"mappings":"","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"util.d.js","names":[],"sources":["../../../src/types/util.d.ts"],"sourcesContent":["import type { RxStorage } from './rx-storage.interface';\n\nexport type MaybePromise = Promise | T;\n\n\nexport type PlainJsonValue =\n string |\n number |\n boolean |\n PlainSimpleJsonObject |\n PlainSimpleJsonObject[] |\n PlainJsonValue[] |\n { [key: string]: PlainJsonValue; };\nexport type PlainSimpleJsonObject = {\n [k: string]: PlainJsonValue | PlainJsonValue[];\n};\n\n/**\n * @link https://stackoverflow.com/a/49670389/3443137\n */\ntype DeepReadonly =\n T extends (infer R)[] ? DeepReadonlyArray :\n T extends Function ? T :\n T extends object ? DeepReadonlyObject :\n T;\n\ninterface DeepReadonlyArray extends ReadonlyArray> { }\n\ntype DeepReadonlyObject = {\n readonly [P in keyof T]: DeepReadonly;\n};\n\nexport type MaybeReadonly = T | Readonly;\n\n\n/**\n * Opposite of DeepReadonly,\n * makes everything mutable again.\n */\ntype DeepMutable = (\n T extends object\n ? {\n -readonly [K in keyof T]: (\n T[K] extends object\n ? DeepMutable\n : T[K]\n )\n }\n : never\n);\n\n/**\n * Can be used like 'keyof'\n * but only represents the string keys, not the Symbols or numbers.\n * @link https://stackoverflow.com/a/51808262/3443137\n */\nexport type StringKeys = Extract;\n\nexport type AnyKeys = { [P in keyof T]?: T[P] | any };\nexport interface AnyObject {\n [k: string]: any;\n}\n\n/**\n * @link https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l\n */\nexport type Override = Omit & T2;\n\n\n\nexport type ById = {\n [id: string]: T;\n};\n\n/**\n * Must be async to support async hashing like from the WebCrypto API.\n */\nexport type HashFunction = (input: string) => Promise;\n\nexport declare type QueryMatcher = (doc: DocType | DeepReadonly) => boolean;\n\n/**\n * To have a deterministic sorting, we cannot return 0,\n * we only return 1 or -1.\n * This ensures that we always end with the same output array, no mather of the\n * pre-sorting of the input array.\n */\nexport declare type DeterministicSortComparator = (a: DocType, b: DocType) => 1 | -1;\n\n/**\n * To test a storage, we need these\n * configuration values.\n */\nexport type RxTestStorage = {\n // can be used to setup async stuff\n readonly init?: () => any;\n // TODO remove name here, it can be read out already via getStorage().name\n readonly name: string;\n readonly getStorage: () => RxStorage;\n /**\n * Returns a storage that is used in performance tests.\n * For example in a browser it should return the storage with an IndexedDB based adapter,\n * while in node.js it must use the filesystem.\n */\n readonly getPerformanceStorage: () => {\n storage: RxStorage;\n /**\n * A description that describes the storage and setting.\n * For example 'dexie-native'.\n */\n description: string;\n };\n /**\n * True if the storage is able to\n * keep data after an instance is closed and opened again.\n */\n readonly hasPersistence: boolean;\n readonly hasMultiInstance: boolean;\n readonly hasAttachments: boolean;\n\n /**\n * Some storages likes the memory-synced storage,\n * are not able to provide a replication while guaranteeing\n * data integrity.\n */\n readonly hasReplication: boolean;\n\n /**\n * To make it possible to test alternative encryption plugins,\n * you can specify hasEncryption to signal\n * the test runner that the given storage already contains an\n * encryption plugin that should be used to test encryption tests.\n * Otherwise the encryption-crypto-js plugin will be tested.\n *\n * hasEncryption must contain a function that is able\n * to create a new password.\n */\n readonly hasEncryption?: () => Promise;\n};\n\n\n/**\n * The paths as strings-type of nested object\n * @link https://stackoverflow.com/a/58436959/3443137\n */\ntype Join = K extends string | number ?\n P extends string | number ?\n `${K}${'' extends P ? '' : '.'}${P}`\n : never : never;\n\nexport type Paths = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: K extends string | number ?\n `${K}` | (Paths extends infer R ? Join : never)\n : never\n }[keyof T] : '';\n\nexport type Leaves = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: Join> }[keyof T] : '';\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\n 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n"],"mappings":"","ignoreList":[]} \ No newline at end of file diff --git a/dist/esm/replication-protocol/downstream.js b/dist/esm/replication-protocol/downstream.js index 29d502ab3cb..9ff7b6c8a38 100644 --- a/dist/esm/replication-protocol/downstream.js +++ b/dist/esm/replication-protocol/downstream.js @@ -206,12 +206,15 @@ export async function startReplicationDownstream(state) { if (!isAssumedMasterEqualToForkState && assumedMaster && assumedMaster.docData._rev && forkStateFullDoc && forkStateFullDoc._meta[state.input.identifier] && getHeightOfRevision(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]) { isAssumedMasterEqualToForkState = true; } - if (forkStateFullDoc && assumedMaster && isAssumedMasterEqualToForkState === false || forkStateFullDoc && !assumedMaster) { + if ((forkStateFullDoc && assumedMaster && isAssumedMasterEqualToForkState === false || forkStateFullDoc && !assumedMaster) && !(forkStateFullDoc._meta.o && forkStateFullDoc._meta.o.hash === identifierHash && forkStateFullDoc._meta.o._rev === getHeightOfRevision(forkStateFullDoc._rev))) { /** * We have a non-upstream-replicated * local write to the fork. - * This means we ignore the downstream of this document - * because anyway the upstream will first resolve the conflict. + * This means either we have to upstream the local + * doc data first, or it means that the fork state was + * synced from the master but the process exited before + * the metadata was written. + * @link https://github.com/pubkey/rxdb/pull/7804 */ return PROMISE_RESOLVE_VOID; } @@ -267,6 +270,17 @@ export async function startReplicationDownstream(state) { if (state.input.keepMeta && masterState._meta) { newForkState._meta = masterState._meta; } + + /** + * Tag the write with its origin so a later downstream run can tell + * "fork differs from assumed master" caused by a local write apart + * from one caused by a lost meta write. A local write bumps the + * revision height and voids the marker. + */ + newForkState._meta.o = { + _rev: !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1, + hash: identifierHash + }; var forkWriteRow = { previous: forkStateFullDoc, document: newForkState diff --git a/dist/esm/replication-protocol/downstream.js.map b/dist/esm/replication-protocol/downstream.js.map index 8a3ad2dddea..6959d8b49f3 100644 --- a/dist/esm/replication-protocol/downstream.js.map +++ b/dist/esm/replication-protocol/downstream.js.map @@ -1 +1 @@ -{"version":3,"file":"downstream.js","names":["firstValueFrom","filter","mergeMap","newRxError","stackCheckpoints","appendToArray","createRevision","ensureNotFalsy","flatClone","getDefaultRevision","getHeightOfRevision","now","PROMISE_RESOLVE_VOID","getLastCheckpointDoc","setCheckpoint","stripAttachmentsDataFromMetaWriteRows","writeDocToDocState","getAssumedMasterState","getMetaWriteRow","startReplicationDownstream","state","input","initialCheckpoint","downstream","checkpointDoc","identifierHash","hashFunction","identifier","replicationHandler","timer","openTasks","addNewTask","task","stats","down","taskWithTime","time","push","streamQueue","then","useTasks","length","events","active","next","innerTaskWithTime","shift","lastTimeMasterChangesRequested","downstreamResyncOnce","downstreamProcessChanges","firstSyncDone","getValue","canceled","sub","masterChangeStream$","pipe","ev","up","s","subscribe","masterChangeStreamEmit","unsubscribe","checkpointQueue","lastCheckpoint","promises","downResult","masterChangesSince","pullBatchSize","documents","checkpoint","persistFromMaster","Promise","all","tasks","docsOfAllTasks","forEach","Error","persistenceQueue","nonPersistedFromMaster","docs","primaryPath","docData","docId","downDocsById","useCheckpoint","docIds","Object","keys","writeRowsToFork","writeRowsToForkById","writeRowsToMeta","useMetaWriteRows","forkInstance","findDocumentsById","currentForkStateList","assumedMasterState","currentForkState","Map","doc","set","map","forkStateFullDoc","get","forkStateDocData","hasAttachments","undefined","masterState","assumedMaster","metaDocument","isResolvedConflict","_rev","isAssumedMasterEqualToForkState","conflictHandler","realMasterState","newDocumentState","r","isEqual","_meta","areStatesExactlyEqual","newForkState","assign","_attachments","lwt","nextRevisionHeight","keepMeta","forkWriteRow","previous","document","bulkWrite","downstreamBulkWriteFlag","forkWriteResult","success","processed","error","status","writeError","metaInstance","metaWriteResult","id","documentId","catch","unhandledError"],"sources":["../../../src/replication-protocol/downstream.ts"],"sourcesContent":["import {\n firstValueFrom,\n filter,\n mergeMap\n} from 'rxjs';\nimport { newRxError } from '../rx-error.ts';\nimport { stackCheckpoints } from '../rx-storage-helper.ts';\nimport type {\n RxStorageInstanceReplicationState,\n BulkWriteRow,\n BulkWriteRowById,\n RxStorageReplicationMeta,\n RxDocumentData,\n ById,\n WithDeleted,\n DocumentsWithCheckpoint,\n WithDeletedAndAttachments\n} from '../types/index.d.ts';\nimport {\n appendToArray,\n createRevision,\n ensureNotFalsy,\n flatClone,\n getDefaultRevision,\n getHeightOfRevision,\n now,\n PROMISE_RESOLVE_VOID\n} from '../plugins/utils/index.ts';\nimport {\n getLastCheckpointDoc,\n setCheckpoint\n} from './checkpoint.ts';\nimport {\n stripAttachmentsDataFromMetaWriteRows,\n writeDocToDocState\n} from './helper.ts';\nimport {\n getAssumedMasterState,\n getMetaWriteRow\n} from './meta-instance.ts';\n\n/**\n * Writes all documents from the master to the fork.\n * The downstream has two operation modes\n * - Sync by iterating over the checkpoints via downstreamResyncOnce()\n * - Sync by listening to the changestream via downstreamProcessChanges()\n * We need this to be able to do initial syncs\n * and still can have fast event based sync when the client is not offline.\n */\nexport async function startReplicationDownstream(\n state: RxStorageInstanceReplicationState\n) {\n if (\n state.input.initialCheckpoint &&\n state.input.initialCheckpoint.downstream\n ) {\n const checkpointDoc = await getLastCheckpointDoc(state, 'down');\n if (!checkpointDoc) {\n await setCheckpoint(\n state,\n 'down',\n state.input.initialCheckpoint.downstream\n );\n }\n }\n\n const identifierHash = await state.input.hashFunction(state.input.identifier);\n const replicationHandler = state.input.replicationHandler;\n\n // used to detect which tasks etc can in it at which order.\n let timer = 0;\n\n\n type Task = DocumentsWithCheckpoint | 'RESYNC';\n type TaskWithTime = {\n time: number;\n task: Task;\n };\n const openTasks: TaskWithTime[] = [];\n\n\n function addNewTask(task: Task): void {\n state.stats.down.addNewTask = state.stats.down.addNewTask + 1;\n const taskWithTime = {\n time: timer++,\n task\n };\n openTasks.push(taskWithTime);\n state.streamQueue.down = state.streamQueue.down\n .then(() => {\n const useTasks: Task[] = [];\n while (openTasks.length > 0) {\n state.events.active.down.next(true);\n const innerTaskWithTime = ensureNotFalsy(openTasks.shift());\n\n /**\n * If the task came in before the last time we started the pull\n * from the master, then we can drop the task.\n */\n if (innerTaskWithTime.time < lastTimeMasterChangesRequested) {\n continue;\n }\n\n if (innerTaskWithTime.task === 'RESYNC') {\n if (useTasks.length === 0) {\n useTasks.push(innerTaskWithTime.task);\n break;\n } else {\n break;\n }\n }\n\n useTasks.push(innerTaskWithTime.task);\n }\n if (useTasks.length === 0) {\n return;\n }\n\n if (useTasks[0] === 'RESYNC') {\n return downstreamResyncOnce();\n } else {\n return downstreamProcessChanges(useTasks);\n }\n }).then(() => {\n state.events.active.down.next(false);\n if (\n !state.firstSyncDone.down.getValue() &&\n !state.events.canceled.getValue()\n ) {\n state.firstSyncDone.down.next(true);\n }\n });\n }\n addNewTask('RESYNC');\n\n /**\n * If a write on the master happens, we have to trigger the downstream.\n * Only do this if not canceled yet, otherwise firstValueFrom errors\n * when running on a completed observable.\n */\n if (!state.events.canceled.getValue()) {\n const sub = replicationHandler\n .masterChangeStream$\n .pipe(\n mergeMap(async (ev) => {\n /**\n * While a push is running, we have to delay all incoming\n * events from the server to not mix up the replication state.\n */\n await firstValueFrom(\n state.events.active.up.pipe(filter(s => !s))\n );\n return ev;\n })\n )\n .subscribe((task: Task) => {\n state.stats.down.masterChangeStreamEmit = state.stats.down.masterChangeStreamEmit + 1;\n addNewTask(task);\n });\n firstValueFrom(\n state.events.canceled.pipe(\n filter(canceled => !!canceled)\n )\n ).then(() => sub.unsubscribe());\n }\n\n\n /**\n * For faster performance, we directly start each write\n * and then await all writes at the end.\n */\n let lastTimeMasterChangesRequested: number = -1;\n async function downstreamResyncOnce() {\n state.stats.down.downstreamResyncOnce = state.stats.down.downstreamResyncOnce + 1;\n if (state.events.canceled.getValue()) {\n return;\n }\n\n state.checkpointQueue = state.checkpointQueue.then(() => getLastCheckpointDoc(state, 'down'));\n let lastCheckpoint: CheckpointType = await state.checkpointQueue;\n\n\n const promises: Promise[] = [];\n while (!state.events.canceled.getValue()) {\n lastTimeMasterChangesRequested = timer++;\n const downResult = await replicationHandler.masterChangesSince(\n lastCheckpoint,\n state.input.pullBatchSize\n );\n\n if (downResult.documents.length === 0) {\n break;\n }\n\n lastCheckpoint = stackCheckpoints([lastCheckpoint, downResult.checkpoint]);\n\n promises.push(\n persistFromMaster(\n downResult.documents,\n lastCheckpoint\n )\n );\n\n /**\n * By definition we stop pull when the pulled documents\n * do not fill up the pullBatchSize because we\n * can assume that the remote has no more documents.\n */\n if (downResult.documents.length < state.input.pullBatchSize) {\n break;\n }\n\n }\n await Promise.all(promises);\n }\n\n\n function downstreamProcessChanges(tasks: Task[]) {\n state.stats.down.downstreamProcessChanges = state.stats.down.downstreamProcessChanges + 1;\n const docsOfAllTasks: WithDeleted[] = [];\n let lastCheckpoint: CheckpointType | undefined = null as any;\n\n tasks.forEach(task => {\n if (task === 'RESYNC') {\n throw new Error('SNH');\n }\n appendToArray(docsOfAllTasks, task.documents);\n lastCheckpoint = stackCheckpoints([lastCheckpoint, task.checkpoint]);\n });\n return persistFromMaster(\n docsOfAllTasks,\n ensureNotFalsy(lastCheckpoint)\n );\n }\n\n\n /**\n * It can happen that the calls to masterChangesSince() or the changeStream()\n * are way faster then how fast the documents can be persisted.\n * Therefore we merge all incoming downResults into the nonPersistedFromMaster object\n * and process them together if possible.\n * This often bundles up single writes and improves performance\n * by processing the documents in bulks.\n */\n let persistenceQueue = PROMISE_RESOLVE_VOID;\n const nonPersistedFromMaster: {\n checkpoint?: CheckpointType;\n docs: ById>;\n } = {\n docs: {}\n };\n\n function persistFromMaster(\n docs: WithDeleted[],\n checkpoint: CheckpointType\n ): Promise {\n const primaryPath = state.primaryPath;\n state.stats.down.persistFromMaster = state.stats.down.persistFromMaster + 1;\n\n /**\n * Add the new docs to the non-persistent list\n */\n docs.forEach(docData => {\n const docId: string = (docData as any)[primaryPath];\n nonPersistedFromMaster.docs[docId] = docData;\n });\n nonPersistedFromMaster.checkpoint = checkpoint;\n\n /**\n * Run in the queue\n * with all open documents from nonPersistedFromMaster.\n */\n persistenceQueue = persistenceQueue.then(() => {\n\n const downDocsById: ById> = nonPersistedFromMaster.docs;\n nonPersistedFromMaster.docs = {};\n const useCheckpoint = nonPersistedFromMaster.checkpoint;\n const docIds = Object.keys(downDocsById);\n\n if (\n state.events.canceled.getValue() ||\n docIds.length === 0\n ) {\n return PROMISE_RESOLVE_VOID;\n }\n\n const writeRowsToFork: BulkWriteRow[] = [];\n const writeRowsToForkById: ById> = {};\n const writeRowsToMeta: BulkWriteRowById> = {};\n const useMetaWriteRows: BulkWriteRow>[] = [];\n\n return Promise.all([\n state.input.forkInstance.findDocumentsById(docIds, true),\n getAssumedMasterState(\n state,\n docIds\n )\n ]).then(([\n currentForkStateList,\n assumedMasterState\n ]) => {\n const currentForkState = new Map>();\n currentForkStateList.forEach(doc => currentForkState.set((doc as any)[primaryPath], doc));\n return Promise.all(\n docIds.map(async (docId) => {\n const forkStateFullDoc: RxDocumentData | undefined = currentForkState.get(docId);\n const forkStateDocData: WithDeletedAndAttachments | undefined = forkStateFullDoc\n ? writeDocToDocState(forkStateFullDoc, state.hasAttachments, false)\n : undefined\n ;\n const masterState = downDocsById[docId];\n const assumedMaster = assumedMasterState[docId];\n\n if (\n assumedMaster &&\n forkStateFullDoc &&\n assumedMaster.metaDocument.isResolvedConflict === forkStateFullDoc._rev\n ) {\n /**\n * The current fork state represents a resolved conflict\n * that first must be send to the master in the upstream.\n * All conflicts are resolved by the upstream.\n */\n // return PROMISE_RESOLVE_VOID;\n await state.streamQueue.up;\n }\n\n let isAssumedMasterEqualToForkState = !assumedMaster || !forkStateDocData ?\n false :\n await state.input.conflictHandler({\n realMasterState: assumedMaster.docData,\n newDocumentState: forkStateDocData\n }, 'downstream-check-if-equal-0').then(r => r.isEqual);\n if (\n !isAssumedMasterEqualToForkState &&\n (\n assumedMaster &&\n (assumedMaster.docData as any)._rev &&\n forkStateFullDoc &&\n forkStateFullDoc._meta[state.input.identifier] &&\n getHeightOfRevision(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]\n )\n ) {\n isAssumedMasterEqualToForkState = true;\n }\n if (\n (\n forkStateFullDoc &&\n assumedMaster &&\n isAssumedMasterEqualToForkState === false\n ) ||\n (\n forkStateFullDoc && !assumedMaster\n )\n ) {\n /**\n * We have a non-upstream-replicated\n * local write to the fork.\n * This means we ignore the downstream of this document\n * because anyway the upstream will first resolve the conflict.\n */\n return PROMISE_RESOLVE_VOID;\n }\n\n const areStatesExactlyEqual = !forkStateDocData\n ? false\n : await state.input.conflictHandler(\n {\n realMasterState: masterState,\n newDocumentState: forkStateDocData\n },\n 'downstream-check-if-equal-1'\n ).then(r => r.isEqual);\n if (\n forkStateDocData &&\n areStatesExactlyEqual\n ) {\n /**\n * Document states are exactly equal.\n * This can happen when the replication is shut down\n * unexpected like when the user goes offline.\n *\n * Only when the assumedMaster is different from the forkState,\n * we have to patch the document in the meta instance.\n */\n if (\n !assumedMaster ||\n isAssumedMasterEqualToForkState === false\n ) {\n useMetaWriteRows.push(\n await getMetaWriteRow(\n state,\n forkStateDocData,\n assumedMaster ? assumedMaster.metaDocument : undefined\n )\n );\n }\n return PROMISE_RESOLVE_VOID;\n }\n\n /**\n * All other master states need to be written to the forkInstance\n * and metaInstance.\n */\n const newForkState = Object.assign(\n {},\n masterState,\n forkStateFullDoc ? {\n _meta: flatClone(forkStateFullDoc._meta),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {},\n _rev: getDefaultRevision()\n } : {\n _meta: {\n lwt: now()\n },\n _rev: getDefaultRevision(),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {}\n }\n );\n /**\n * If the remote works with revisions,\n * we store the height of the next fork-state revision\n * inside of the documents meta data.\n * By doing so we can filter it out in the upstream\n * and detect the document as being equal to master or not.\n * This is used for example in the CouchDB replication plugin.\n */\n if ((masterState as any)._rev) {\n const nextRevisionHeight = !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1;\n newForkState._meta[state.input.identifier] = nextRevisionHeight;\n if (state.input.keepMeta) {\n newForkState._rev = (masterState as any)._rev;\n }\n }\n if (\n state.input.keepMeta &&\n (masterState as any)._meta\n ) {\n newForkState._meta = (masterState as any)._meta;\n }\n\n const forkWriteRow = {\n previous: forkStateFullDoc,\n document: newForkState\n };\n\n forkWriteRow.document._rev = forkWriteRow.document._rev ? forkWriteRow.document._rev : createRevision(\n identifierHash,\n forkWriteRow.previous\n );\n writeRowsToFork.push(forkWriteRow);\n writeRowsToForkById[docId] = forkWriteRow;\n writeRowsToMeta[docId] = await getMetaWriteRow(\n state,\n masterState,\n assumedMaster ? assumedMaster.metaDocument : undefined\n );\n })\n );\n }).then(async () => {\n if (writeRowsToFork.length > 0) {\n return state.input.forkInstance.bulkWrite(\n writeRowsToFork,\n await state.downstreamBulkWriteFlag\n ).then((forkWriteResult) => {\n forkWriteResult.success.forEach(doc => {\n const docId = (doc as any)[primaryPath];\n state.events.processed.down.next(writeRowsToForkById[docId]);\n useMetaWriteRows.push(writeRowsToMeta[docId]);\n });\n forkWriteResult.error.forEach(error => {\n /**\n * We do not have to care about downstream conflict errors here\n * because on conflict, it will be solved locally and result in another write.\n */\n if (error.status === 409) {\n return;\n }\n // other non-conflict errors must be handled\n state.events.error.next(newRxError('RC_PULL', {\n writeError: error\n }));\n });\n });\n }\n }).then(() => {\n if (useMetaWriteRows.length > 0) {\n return state.input.metaInstance.bulkWrite(\n stripAttachmentsDataFromMetaWriteRows(state, useMetaWriteRows),\n 'replication-down-write-meta'\n ).then(metaWriteResult => {\n metaWriteResult.error\n .forEach(writeError => {\n state.events.error.next(newRxError('RC_PULL', {\n id: writeError.documentId,\n writeError\n }));\n });\n });\n }\n }).then(() => {\n /**\n * For better performance we do not await checkpoint writes,\n * but to ensure order on parallel checkpoint writes,\n * we have to use a queue.\n */\n setCheckpoint(\n state,\n 'down',\n useCheckpoint\n );\n });\n }).catch(unhandledError => state.events.error.next(unhandledError));\n return persistenceQueue;\n }\n}\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"downstream.js","names":["firstValueFrom","filter","mergeMap","newRxError","stackCheckpoints","appendToArray","createRevision","ensureNotFalsy","flatClone","getDefaultRevision","getHeightOfRevision","now","PROMISE_RESOLVE_VOID","getLastCheckpointDoc","setCheckpoint","stripAttachmentsDataFromMetaWriteRows","writeDocToDocState","getAssumedMasterState","getMetaWriteRow","startReplicationDownstream","state","input","initialCheckpoint","downstream","checkpointDoc","identifierHash","hashFunction","identifier","replicationHandler","timer","openTasks","addNewTask","task","stats","down","taskWithTime","time","push","streamQueue","then","useTasks","length","events","active","next","innerTaskWithTime","shift","lastTimeMasterChangesRequested","downstreamResyncOnce","downstreamProcessChanges","firstSyncDone","getValue","canceled","sub","masterChangeStream$","pipe","ev","up","s","subscribe","masterChangeStreamEmit","unsubscribe","checkpointQueue","lastCheckpoint","promises","downResult","masterChangesSince","pullBatchSize","documents","checkpoint","persistFromMaster","Promise","all","tasks","docsOfAllTasks","forEach","Error","persistenceQueue","nonPersistedFromMaster","docs","primaryPath","docData","docId","downDocsById","useCheckpoint","docIds","Object","keys","writeRowsToFork","writeRowsToForkById","writeRowsToMeta","useMetaWriteRows","forkInstance","findDocumentsById","currentForkStateList","assumedMasterState","currentForkState","Map","doc","set","map","forkStateFullDoc","get","forkStateDocData","hasAttachments","undefined","masterState","assumedMaster","metaDocument","isResolvedConflict","_rev","isAssumedMasterEqualToForkState","conflictHandler","realMasterState","newDocumentState","r","isEqual","_meta","o","hash","areStatesExactlyEqual","newForkState","assign","_attachments","lwt","nextRevisionHeight","keepMeta","forkWriteRow","previous","document","bulkWrite","downstreamBulkWriteFlag","forkWriteResult","success","processed","error","status","writeError","metaInstance","metaWriteResult","id","documentId","catch","unhandledError"],"sources":["../../../src/replication-protocol/downstream.ts"],"sourcesContent":["import {\n firstValueFrom,\n filter,\n mergeMap\n} from 'rxjs';\nimport { newRxError } from '../rx-error.ts';\nimport { stackCheckpoints } from '../rx-storage-helper.ts';\nimport type {\n RxStorageInstanceReplicationState,\n BulkWriteRow,\n BulkWriteRowById,\n RxStorageReplicationMeta,\n RxDocumentData,\n ById,\n WithDeleted,\n DocumentsWithCheckpoint,\n WithDeletedAndAttachments\n} from '../types/index.d.ts';\nimport {\n appendToArray,\n createRevision,\n ensureNotFalsy,\n flatClone,\n getDefaultRevision,\n getHeightOfRevision,\n now,\n PROMISE_RESOLVE_VOID\n} from '../plugins/utils/index.ts';\nimport {\n getLastCheckpointDoc,\n setCheckpoint\n} from './checkpoint.ts';\nimport {\n stripAttachmentsDataFromMetaWriteRows,\n writeDocToDocState\n} from './helper.ts';\nimport {\n getAssumedMasterState,\n getMetaWriteRow\n} from './meta-instance.ts';\n\n/**\n * Writes all documents from the master to the fork.\n * The downstream has two operation modes\n * - Sync by iterating over the checkpoints via downstreamResyncOnce()\n * - Sync by listening to the changestream via downstreamProcessChanges()\n * We need this to be able to do initial syncs\n * and still can have fast event based sync when the client is not offline.\n */\nexport async function startReplicationDownstream(\n state: RxStorageInstanceReplicationState\n) {\n if (\n state.input.initialCheckpoint &&\n state.input.initialCheckpoint.downstream\n ) {\n const checkpointDoc = await getLastCheckpointDoc(state, 'down');\n if (!checkpointDoc) {\n await setCheckpoint(\n state,\n 'down',\n state.input.initialCheckpoint.downstream\n );\n }\n }\n\n const identifierHash = await state.input.hashFunction(state.input.identifier);\n const replicationHandler = state.input.replicationHandler;\n\n // used to detect which tasks etc can in it at which order.\n let timer = 0;\n\n\n type Task = DocumentsWithCheckpoint | 'RESYNC';\n type TaskWithTime = {\n time: number;\n task: Task;\n };\n const openTasks: TaskWithTime[] = [];\n\n\n function addNewTask(task: Task): void {\n state.stats.down.addNewTask = state.stats.down.addNewTask + 1;\n const taskWithTime = {\n time: timer++,\n task\n };\n openTasks.push(taskWithTime);\n state.streamQueue.down = state.streamQueue.down\n .then(() => {\n const useTasks: Task[] = [];\n while (openTasks.length > 0) {\n state.events.active.down.next(true);\n const innerTaskWithTime = ensureNotFalsy(openTasks.shift());\n\n /**\n * If the task came in before the last time we started the pull\n * from the master, then we can drop the task.\n */\n if (innerTaskWithTime.time < lastTimeMasterChangesRequested) {\n continue;\n }\n\n if (innerTaskWithTime.task === 'RESYNC') {\n if (useTasks.length === 0) {\n useTasks.push(innerTaskWithTime.task);\n break;\n } else {\n break;\n }\n }\n\n useTasks.push(innerTaskWithTime.task);\n }\n if (useTasks.length === 0) {\n return;\n }\n\n if (useTasks[0] === 'RESYNC') {\n return downstreamResyncOnce();\n } else {\n return downstreamProcessChanges(useTasks);\n }\n }).then(() => {\n state.events.active.down.next(false);\n if (\n !state.firstSyncDone.down.getValue() &&\n !state.events.canceled.getValue()\n ) {\n state.firstSyncDone.down.next(true);\n }\n });\n }\n addNewTask('RESYNC');\n\n /**\n * If a write on the master happens, we have to trigger the downstream.\n * Only do this if not canceled yet, otherwise firstValueFrom errors\n * when running on a completed observable.\n */\n if (!state.events.canceled.getValue()) {\n const sub = replicationHandler\n .masterChangeStream$\n .pipe(\n mergeMap(async (ev) => {\n /**\n * While a push is running, we have to delay all incoming\n * events from the server to not mix up the replication state.\n */\n await firstValueFrom(\n state.events.active.up.pipe(filter(s => !s))\n );\n return ev;\n })\n )\n .subscribe((task: Task) => {\n state.stats.down.masterChangeStreamEmit = state.stats.down.masterChangeStreamEmit + 1;\n addNewTask(task);\n });\n firstValueFrom(\n state.events.canceled.pipe(\n filter(canceled => !!canceled)\n )\n ).then(() => sub.unsubscribe());\n }\n\n\n /**\n * For faster performance, we directly start each write\n * and then await all writes at the end.\n */\n let lastTimeMasterChangesRequested: number = -1;\n async function downstreamResyncOnce() {\n state.stats.down.downstreamResyncOnce = state.stats.down.downstreamResyncOnce + 1;\n if (state.events.canceled.getValue()) {\n return;\n }\n\n state.checkpointQueue = state.checkpointQueue.then(() => getLastCheckpointDoc(state, 'down'));\n let lastCheckpoint: CheckpointType = await state.checkpointQueue;\n\n\n const promises: Promise[] = [];\n while (!state.events.canceled.getValue()) {\n lastTimeMasterChangesRequested = timer++;\n const downResult = await replicationHandler.masterChangesSince(\n lastCheckpoint,\n state.input.pullBatchSize\n );\n\n if (downResult.documents.length === 0) {\n break;\n }\n\n lastCheckpoint = stackCheckpoints([lastCheckpoint, downResult.checkpoint]);\n\n promises.push(\n persistFromMaster(\n downResult.documents,\n lastCheckpoint\n )\n );\n\n /**\n * By definition we stop pull when the pulled documents\n * do not fill up the pullBatchSize because we\n * can assume that the remote has no more documents.\n */\n if (downResult.documents.length < state.input.pullBatchSize) {\n break;\n }\n\n }\n await Promise.all(promises);\n }\n\n\n function downstreamProcessChanges(tasks: Task[]) {\n state.stats.down.downstreamProcessChanges = state.stats.down.downstreamProcessChanges + 1;\n const docsOfAllTasks: WithDeleted[] = [];\n let lastCheckpoint: CheckpointType | undefined = null as any;\n\n tasks.forEach(task => {\n if (task === 'RESYNC') {\n throw new Error('SNH');\n }\n appendToArray(docsOfAllTasks, task.documents);\n lastCheckpoint = stackCheckpoints([lastCheckpoint, task.checkpoint]);\n });\n return persistFromMaster(\n docsOfAllTasks,\n ensureNotFalsy(lastCheckpoint)\n );\n }\n\n\n /**\n * It can happen that the calls to masterChangesSince() or the changeStream()\n * are way faster then how fast the documents can be persisted.\n * Therefore we merge all incoming downResults into the nonPersistedFromMaster object\n * and process them together if possible.\n * This often bundles up single writes and improves performance\n * by processing the documents in bulks.\n */\n let persistenceQueue = PROMISE_RESOLVE_VOID;\n const nonPersistedFromMaster: {\n checkpoint?: CheckpointType;\n docs: ById>;\n } = {\n docs: {}\n };\n\n function persistFromMaster(\n docs: WithDeleted[],\n checkpoint: CheckpointType\n ): Promise {\n const primaryPath = state.primaryPath;\n state.stats.down.persistFromMaster = state.stats.down.persistFromMaster + 1;\n\n /**\n * Add the new docs to the non-persistent list\n */\n docs.forEach(docData => {\n const docId: string = (docData as any)[primaryPath];\n nonPersistedFromMaster.docs[docId] = docData;\n });\n nonPersistedFromMaster.checkpoint = checkpoint;\n\n /**\n * Run in the queue\n * with all open documents from nonPersistedFromMaster.\n */\n persistenceQueue = persistenceQueue.then(() => {\n\n const downDocsById: ById> = nonPersistedFromMaster.docs;\n nonPersistedFromMaster.docs = {};\n const useCheckpoint = nonPersistedFromMaster.checkpoint;\n const docIds = Object.keys(downDocsById);\n\n if (\n state.events.canceled.getValue() ||\n docIds.length === 0\n ) {\n return PROMISE_RESOLVE_VOID;\n }\n\n const writeRowsToFork: BulkWriteRow[] = [];\n const writeRowsToForkById: ById> = {};\n const writeRowsToMeta: BulkWriteRowById> = {};\n const useMetaWriteRows: BulkWriteRow>[] = [];\n\n return Promise.all([\n state.input.forkInstance.findDocumentsById(docIds, true),\n getAssumedMasterState(\n state,\n docIds\n )\n ]).then(([\n currentForkStateList,\n assumedMasterState\n ]) => {\n const currentForkState = new Map>();\n currentForkStateList.forEach(doc => currentForkState.set((doc as any)[primaryPath], doc));\n return Promise.all(\n docIds.map(async (docId) => {\n const forkStateFullDoc: RxDocumentData | undefined = currentForkState.get(docId);\n const forkStateDocData: WithDeletedAndAttachments | undefined = forkStateFullDoc\n ? writeDocToDocState(forkStateFullDoc, state.hasAttachments, false)\n : undefined\n ;\n const masterState = downDocsById[docId];\n const assumedMaster = assumedMasterState[docId];\n\n if (\n assumedMaster &&\n forkStateFullDoc &&\n assumedMaster.metaDocument.isResolvedConflict === forkStateFullDoc._rev\n ) {\n /**\n * The current fork state represents a resolved conflict\n * that first must be send to the master in the upstream.\n * All conflicts are resolved by the upstream.\n */\n // return PROMISE_RESOLVE_VOID;\n await state.streamQueue.up;\n }\n\n let isAssumedMasterEqualToForkState = !assumedMaster || !forkStateDocData ?\n false :\n await state.input.conflictHandler({\n realMasterState: assumedMaster.docData,\n newDocumentState: forkStateDocData\n }, 'downstream-check-if-equal-0').then(r => r.isEqual);\n if (\n !isAssumedMasterEqualToForkState &&\n (\n assumedMaster &&\n (assumedMaster.docData as any)._rev &&\n forkStateFullDoc &&\n forkStateFullDoc._meta[state.input.identifier] &&\n getHeightOfRevision(forkStateFullDoc._rev) === forkStateFullDoc._meta[state.input.identifier]\n )\n ) {\n isAssumedMasterEqualToForkState = true;\n }\n if (\n (\n (\n forkStateFullDoc &&\n assumedMaster &&\n isAssumedMasterEqualToForkState === false\n ) ||\n (\n forkStateFullDoc && !assumedMaster\n )\n ) &&\n !(\n forkStateFullDoc._meta.o &&\n (\n forkStateFullDoc._meta.o.hash === identifierHash &&\n forkStateFullDoc._meta.o._rev === getHeightOfRevision(forkStateFullDoc._rev)\n )\n )\n ) {\n /**\n * We have a non-upstream-replicated\n * local write to the fork.\n * This means either we have to upstream the local\n * doc data first, or it means that the fork state was\n * synced from the master but the process exited before\n * the metadata was written.\n * @link https://github.com/pubkey/rxdb/pull/7804\n */\n return PROMISE_RESOLVE_VOID;\n }\n\n const areStatesExactlyEqual = !forkStateDocData\n ? false\n : await state.input.conflictHandler(\n {\n realMasterState: masterState,\n newDocumentState: forkStateDocData\n },\n 'downstream-check-if-equal-1'\n ).then(r => r.isEqual);\n if (\n forkStateDocData &&\n areStatesExactlyEqual\n ) {\n /**\n * Document states are exactly equal.\n * This can happen when the replication is shut down\n * unexpected like when the user goes offline.\n *\n * Only when the assumedMaster is different from the forkState,\n * we have to patch the document in the meta instance.\n */\n if (\n !assumedMaster ||\n isAssumedMasterEqualToForkState === false\n ) {\n useMetaWriteRows.push(\n await getMetaWriteRow(\n state,\n forkStateDocData,\n assumedMaster ? assumedMaster.metaDocument : undefined\n )\n );\n }\n return PROMISE_RESOLVE_VOID;\n }\n\n /**\n * All other master states need to be written to the forkInstance\n * and metaInstance.\n */\n const newForkState = Object.assign(\n {},\n masterState,\n forkStateFullDoc ? {\n _meta: flatClone(forkStateFullDoc._meta),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {},\n _rev: getDefaultRevision()\n } : {\n _meta: {\n lwt: now()\n },\n _rev: getDefaultRevision(),\n _attachments: state.hasAttachments && masterState._attachments ? masterState._attachments : {}\n }\n );\n /**\n * If the remote works with revisions,\n * we store the height of the next fork-state revision\n * inside of the documents meta data.\n * By doing so we can filter it out in the upstream\n * and detect the document as being equal to master or not.\n * This is used for example in the CouchDB replication plugin.\n */\n if ((masterState as any)._rev) {\n const nextRevisionHeight = !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1;\n newForkState._meta[state.input.identifier] = nextRevisionHeight;\n if (state.input.keepMeta) {\n newForkState._rev = (masterState as any)._rev;\n }\n }\n if (\n state.input.keepMeta &&\n (masterState as any)._meta\n ) {\n newForkState._meta = (masterState as any)._meta;\n }\n\n /**\n * Tag the write with its origin so a later downstream run can tell\n * \"fork differs from assumed master\" caused by a local write apart\n * from one caused by a lost meta write. A local write bumps the\n * revision height and voids the marker.\n */\n newForkState._meta.o = {\n _rev: !forkStateFullDoc ? 1 : getHeightOfRevision(forkStateFullDoc._rev) + 1,\n hash: identifierHash\n };\n\n const forkWriteRow = {\n previous: forkStateFullDoc,\n document: newForkState\n };\n\n forkWriteRow.document._rev = forkWriteRow.document._rev ? forkWriteRow.document._rev : createRevision(\n identifierHash,\n forkWriteRow.previous\n );\n writeRowsToFork.push(forkWriteRow);\n writeRowsToForkById[docId] = forkWriteRow;\n writeRowsToMeta[docId] = await getMetaWriteRow(\n state,\n masterState,\n assumedMaster ? assumedMaster.metaDocument : undefined\n );\n })\n );\n }).then(async () => {\n if (writeRowsToFork.length > 0) {\n return state.input.forkInstance.bulkWrite(\n writeRowsToFork,\n await state.downstreamBulkWriteFlag\n ).then((forkWriteResult) => {\n forkWriteResult.success.forEach(doc => {\n const docId = (doc as any)[primaryPath];\n state.events.processed.down.next(writeRowsToForkById[docId]);\n useMetaWriteRows.push(writeRowsToMeta[docId]);\n });\n forkWriteResult.error.forEach(error => {\n /**\n * We do not have to care about downstream conflict errors here\n * because on conflict, it will be solved locally and result in another write.\n */\n if (error.status === 409) {\n return;\n }\n // other non-conflict errors must be handled\n state.events.error.next(newRxError('RC_PULL', {\n writeError: error\n }));\n });\n });\n }\n }).then(() => {\n if (useMetaWriteRows.length > 0) {\n return state.input.metaInstance.bulkWrite(\n stripAttachmentsDataFromMetaWriteRows(state, useMetaWriteRows),\n 'replication-down-write-meta'\n ).then(metaWriteResult => {\n metaWriteResult.error\n .forEach(writeError => {\n state.events.error.next(newRxError('RC_PULL', {\n id: writeError.documentId,\n writeError\n }));\n });\n });\n }\n }).then(() => {\n /**\n * For better performance we do not await checkpoint writes,\n * but to ensure order on parallel checkpoint writes,\n * we have to use a queue.\n */\n setCheckpoint(\n state,\n 'down',\n useCheckpoint\n );\n });\n }).catch(unhandledError => state.events.error.next(unhandledError));\n return persistenceQueue;\n }\n}\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file diff --git a/dist/esm/types/rx-document.d.js.map b/dist/esm/types/rx-document.d.js.map index eb6baf2addd..c5a9e8f8a60 100644 --- a/dist/esm/types/rx-document.d.js.map +++ b/dist/esm/types/rx-document.d.js.map @@ -1 +1 @@ -{"version":3,"file":"rx-document.d.js","names":[],"sources":["../../../src/types/rx-document.d.ts"],"sourcesContent":["import {\n Observable\n} from 'rxjs';\n\nimport type {\n RxCollection,\n} from './rx-collection.d.ts';\nimport type {\n RxAttachment,\n RxAttachmentCreator\n} from './rx-attachment.d.ts';\nimport type { RxDocumentData, WithDeleted } from './rx-storage.d.ts';\nimport type { RxChangeEvent } from './rx-change-event.d.ts';\nimport type { DeepReadonly, MaybePromise, PlainJsonValue } from './util.d.ts';\nimport type { UpdateQuery } from './plugins/update.d.ts';\nimport type { CRDTEntry } from './plugins/crdt.d.ts';\n\n\n\nexport type RxDocument = RxDocumentBase<\n RxDocumentType,\n OrmMethods,\n Reactivity\n> & RxDocumentType & OrmMethods & ExtendObservables & ExtendReactivity;\n\n\n/**\n * Extend the base properties by the property$ fields\n * so it knows that RxDocument.age also has RxDocument.age$ which is\n * an observable.\n * TODO how to do this for the nested fields?\n */\ntype ExtendObservables = {\n [P in keyof RxDocumentType as `${string & P}$`]: Observable;\n};\n\ntype ExtendReactivity = {\n [P in keyof RxDocumentType as `${string & P}$$`]: Reactivity;\n};\n\n/**\n * The public facing modify update function.\n * It only gets the document parts as input, that\n * are mutateable by the user.\n */\nexport type ModifyFunction = (\n doc: WithDeleted\n) => MaybePromise> | MaybePromise;\n\n/**\n * Meta data that is attached to each document by RxDB.\n */\nexport type RxDocumentMeta = {\n /**\n * Last write time.\n * Unix epoch in milliseconds.\n */\n lwt: number;\n\n /**\n * Any other value can be attached to the _meta data.\n * Mostly done by plugins to mark documents.\n */\n [k: string]: PlainJsonValue;\n};\n\nexport declare interface RxDocumentBase {\n isInstanceOfRxDocument: true;\n collection: RxCollection;\n readonly deleted: boolean;\n\n readonly $: Observable>;\n readonly $$: Reactivity;\n readonly deleted$: Observable;\n readonly deleted$$: Reactivity;\n\n readonly primary: string;\n readonly allAttachments$: Observable[]>;\n\n // internal things\n _data: RxDocumentData;\n primaryPath: string;\n revision: string;\n /**\n * Used to de-duplicate the enriched property objects\n * of the document.\n */\n _propertyCache: Map;\n $emit(cE: RxChangeEvent): void;\n _saveData(newData: any, oldData: any): Promise>;\n // /internal things\n\n // Returns the latest state of the document\n getLatest(): RxDocument;\n\n\n get$(path: string): Observable;\n get$$(path: string): Reactivity;\n get(objPath: string): DeepReadonly;\n populate(objPath: string): Promise | any | null>;\n\n /**\n * mutate the document with a function\n */\n modify(mutationFunction: ModifyFunction, context?: string): Promise>;\n incrementalModify(mutationFunction: ModifyFunction, context?: string): Promise>;\n\n /**\n * patches the given properties\n */\n patch(patch: Partial): Promise>;\n incrementalPatch(patch: Partial): Promise>;\n\n update(updateObj: UpdateQuery): Promise>;\n incrementalUpdate(updateObj: UpdateQuery): Promise>;\n\n updateCRDT(updateObj: CRDTEntry | CRDTEntry[]): Promise>;\n\n remove(): Promise>;\n incrementalRemove(): Promise>;\n\n // only for temporary documents\n set(objPath: string, value: any): RxDocument;\n save(): Promise;\n\n // attachments\n putAttachment(\n creator: RxAttachmentCreator\n ): Promise>;\n getAttachment(id: string): RxAttachment | null;\n allAttachments(): RxAttachment[];\n\n toJSON(withRevAndAttachments: true): DeepReadonly>;\n toJSON(withRevAndAttachments?: false): DeepReadonly;\n\n toMutableJSON(withRevAndAttachments: true): RxDocumentData;\n toMutableJSON(withRevAndAttachments?: false): RxDocType;\n\n destroy(): void;\n}\n"],"mappings":"","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"rx-document.d.js","names":[],"sources":["../../../src/types/rx-document.d.ts"],"sourcesContent":["import {\n Observable\n} from 'rxjs';\n\nimport type {\n RxCollection,\n} from './rx-collection.d.ts';\nimport type {\n RxAttachment,\n RxAttachmentCreator\n} from './rx-attachment.d.ts';\nimport type { RxDocumentData, WithDeleted } from './rx-storage.d.ts';\nimport type { RxChangeEvent } from './rx-change-event.d.ts';\nimport type { DeepReadonly, MaybePromise, PlainJsonValue } from './util.d.ts';\nimport type { UpdateQuery } from './plugins/update.d.ts';\nimport type { CRDTEntry } from './plugins/crdt.d.ts';\n\n\n\nexport type RxDocument = RxDocumentBase<\n RxDocumentType,\n OrmMethods,\n Reactivity\n> & RxDocumentType & OrmMethods & ExtendObservables & ExtendReactivity;\n\n\n/**\n * Extend the base properties by the property$ fields\n * so it knows that RxDocument.age also has RxDocument.age$ which is\n * an observable.\n * TODO how to do this for the nested fields?\n */\ntype ExtendObservables = {\n [P in keyof RxDocumentType as `${string & P}$`]: Observable;\n};\n\ntype ExtendReactivity = {\n [P in keyof RxDocumentType as `${string & P}$$`]: Reactivity;\n};\n\n/**\n * The public facing modify update function.\n * It only gets the document parts as input, that\n * are mutateable by the user.\n */\nexport type ModifyFunction = (\n doc: WithDeleted\n) => MaybePromise> | MaybePromise;\n\n/**\n * Meta data that is attached to each document by RxDB.\n */\nexport type RxDocumentMeta = {\n /**\n * Last write time.\n * Unix epoch in milliseconds.\n */\n lwt: number;\n\n /**\n * The replication plugins \"tags\" the origin\n * of writes to later know if a write came from\n * the replication or was done locally.\n */\n o?: {\n hash: string;\n _rev: number;\n };\n\n /**\n * Any other value can be attached to the _meta data.\n * Mostly done by plugins to mark documents.\n */\n [k: string]: PlainJsonValue | undefined;\n};\n\nexport declare interface RxDocumentBase {\n isInstanceOfRxDocument: true;\n collection: RxCollection;\n readonly deleted: boolean;\n\n readonly $: Observable>;\n readonly $$: Reactivity;\n readonly deleted$: Observable;\n readonly deleted$$: Reactivity;\n\n readonly primary: string;\n readonly allAttachments$: Observable[]>;\n\n // internal things\n _data: RxDocumentData;\n primaryPath: string;\n revision: string;\n /**\n * Used to de-duplicate the enriched property objects\n * of the document.\n */\n _propertyCache: Map;\n $emit(cE: RxChangeEvent): void;\n _saveData(newData: any, oldData: any): Promise>;\n // /internal things\n\n // Returns the latest state of the document\n getLatest(): RxDocument;\n\n\n get$(path: string): Observable;\n get$$(path: string): Reactivity;\n get(objPath: string): DeepReadonly;\n populate(objPath: string): Promise | any | null>;\n\n /**\n * mutate the document with a function\n */\n modify(mutationFunction: ModifyFunction, context?: string): Promise>;\n incrementalModify(mutationFunction: ModifyFunction, context?: string): Promise>;\n\n /**\n * patches the given properties\n */\n patch(patch: Partial): Promise>;\n incrementalPatch(patch: Partial): Promise>;\n\n update(updateObj: UpdateQuery): Promise>;\n incrementalUpdate(updateObj: UpdateQuery): Promise>;\n\n updateCRDT(updateObj: CRDTEntry | CRDTEntry[]): Promise>;\n\n remove(): Promise>;\n incrementalRemove(): Promise>;\n\n // only for temporary documents\n set(objPath: string, value: any): RxDocument;\n save(): Promise;\n\n // attachments\n putAttachment(\n creator: RxAttachmentCreator\n ): Promise>;\n getAttachment(id: string): RxAttachment | null;\n allAttachments(): RxAttachment[];\n\n toJSON(withRevAndAttachments: true): DeepReadonly>;\n toJSON(withRevAndAttachments?: false): DeepReadonly;\n\n toMutableJSON(withRevAndAttachments: true): RxDocumentData;\n toMutableJSON(withRevAndAttachments?: false): RxDocType;\n\n destroy(): void;\n}\n"],"mappings":"","ignoreList":[]} \ No newline at end of file diff --git a/dist/esm/types/util.d.js.map b/dist/esm/types/util.d.js.map index 9d1b26e0974..08295e33e92 100644 --- a/dist/esm/types/util.d.js.map +++ b/dist/esm/types/util.d.js.map @@ -1 +1 @@ -{"version":3,"file":"util.d.js","names":[],"sources":["../../../src/types/util.d.ts"],"sourcesContent":["import type { RxStorage } from './rx-storage.interface';\n\nexport type MaybePromise = Promise | T;\n\n\nexport type PlainJsonValue = string | number | boolean | PlainSimpleJsonObject | PlainSimpleJsonObject[] | PlainJsonValue[];\nexport type PlainSimpleJsonObject = {\n [k: string]: PlainJsonValue | PlainJsonValue[];\n};\n\n/**\n * @link https://stackoverflow.com/a/49670389/3443137\n */\ntype DeepReadonly =\n T extends (infer R)[] ? DeepReadonlyArray :\n T extends Function ? T :\n T extends object ? DeepReadonlyObject :\n T;\n\ninterface DeepReadonlyArray extends ReadonlyArray> { }\n\ntype DeepReadonlyObject = {\n readonly [P in keyof T]: DeepReadonly;\n};\n\nexport type MaybeReadonly = T | Readonly;\n\n\n/**\n * Opposite of DeepReadonly,\n * makes everything mutable again.\n */\ntype DeepMutable = (\n T extends object\n ? {\n -readonly [K in keyof T]: (\n T[K] extends object\n ? DeepMutable\n : T[K]\n )\n }\n : never\n);\n\n/**\n * Can be used like 'keyof'\n * but only represents the string keys, not the Symbols or numbers.\n * @link https://stackoverflow.com/a/51808262/3443137\n */\nexport type StringKeys = Extract;\n\nexport type AnyKeys = { [P in keyof T]?: T[P] | any };\nexport interface AnyObject {\n [k: string]: any;\n}\n\n/**\n * @link https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l\n */\nexport type Override = Omit & T2;\n\n\n\nexport type ById = {\n [id: string]: T;\n};\n\n/**\n * Must be async to support async hashing like from the WebCrypto API.\n */\nexport type HashFunction = (input: string) => Promise;\n\nexport declare type QueryMatcher = (doc: DocType | DeepReadonly) => boolean;\n\n/**\n * To have a deterministic sorting, we cannot return 0,\n * we only return 1 or -1.\n * This ensures that we always end with the same output array, no mather of the\n * pre-sorting of the input array.\n */\nexport declare type DeterministicSortComparator = (a: DocType, b: DocType) => 1 | -1;\n\n/**\n * To test a storage, we need these\n * configuration values.\n */\nexport type RxTestStorage = {\n // can be used to setup async stuff\n readonly init?: () => any;\n // TODO remove name here, it can be read out already via getStorage().name\n readonly name: string;\n readonly getStorage: () => RxStorage;\n /**\n * Returns a storage that is used in performance tests.\n * For example in a browser it should return the storage with an IndexedDB based adapter,\n * while in node.js it must use the filesystem.\n */\n readonly getPerformanceStorage: () => {\n storage: RxStorage;\n /**\n * A description that describes the storage and setting.\n * For example 'dexie-native'.\n */\n description: string;\n };\n /**\n * True if the storage is able to\n * keep data after an instance is closed and opened again.\n */\n readonly hasPersistence: boolean;\n readonly hasMultiInstance: boolean;\n readonly hasAttachments: boolean;\n\n /**\n * Some storages likes the memory-synced storage,\n * are not able to provide a replication while guaranteeing\n * data integrity.\n */\n readonly hasReplication: boolean;\n\n /**\n * To make it possible to test alternative encryption plugins,\n * you can specify hasEncryption to signal\n * the test runner that the given storage already contains an\n * encryption plugin that should be used to test encryption tests.\n * Otherwise the encryption-crypto-js plugin will be tested.\n *\n * hasEncryption must contain a function that is able\n * to create a new password.\n */\n readonly hasEncryption?: () => Promise;\n};\n\n\n/**\n * The paths as strings-type of nested object\n * @link https://stackoverflow.com/a/58436959/3443137\n */\ntype Join = K extends string | number ?\n P extends string | number ?\n `${K}${'' extends P ? '' : '.'}${P}`\n : never : never;\n\nexport type Paths = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: K extends string | number ?\n `${K}` | (Paths extends infer R ? Join : never)\n : never\n }[keyof T] : '';\n\nexport type Leaves = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: Join> }[keyof T] : '';\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\n 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n"],"mappings":"","ignoreList":[]} \ No newline at end of file +{"version":3,"file":"util.d.js","names":[],"sources":["../../../src/types/util.d.ts"],"sourcesContent":["import type { RxStorage } from './rx-storage.interface';\n\nexport type MaybePromise = Promise | T;\n\n\nexport type PlainJsonValue =\n string |\n number |\n boolean |\n PlainSimpleJsonObject |\n PlainSimpleJsonObject[] |\n PlainJsonValue[] |\n { [key: string]: PlainJsonValue; };\nexport type PlainSimpleJsonObject = {\n [k: string]: PlainJsonValue | PlainJsonValue[];\n};\n\n/**\n * @link https://stackoverflow.com/a/49670389/3443137\n */\ntype DeepReadonly =\n T extends (infer R)[] ? DeepReadonlyArray :\n T extends Function ? T :\n T extends object ? DeepReadonlyObject :\n T;\n\ninterface DeepReadonlyArray extends ReadonlyArray> { }\n\ntype DeepReadonlyObject = {\n readonly [P in keyof T]: DeepReadonly;\n};\n\nexport type MaybeReadonly = T | Readonly;\n\n\n/**\n * Opposite of DeepReadonly,\n * makes everything mutable again.\n */\ntype DeepMutable = (\n T extends object\n ? {\n -readonly [K in keyof T]: (\n T[K] extends object\n ? DeepMutable\n : T[K]\n )\n }\n : never\n);\n\n/**\n * Can be used like 'keyof'\n * but only represents the string keys, not the Symbols or numbers.\n * @link https://stackoverflow.com/a/51808262/3443137\n */\nexport type StringKeys = Extract;\n\nexport type AnyKeys = { [P in keyof T]?: T[P] | any };\nexport interface AnyObject {\n [k: string]: any;\n}\n\n/**\n * @link https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l\n */\nexport type Override = Omit & T2;\n\n\n\nexport type ById = {\n [id: string]: T;\n};\n\n/**\n * Must be async to support async hashing like from the WebCrypto API.\n */\nexport type HashFunction = (input: string) => Promise;\n\nexport declare type QueryMatcher = (doc: DocType | DeepReadonly) => boolean;\n\n/**\n * To have a deterministic sorting, we cannot return 0,\n * we only return 1 or -1.\n * This ensures that we always end with the same output array, no mather of the\n * pre-sorting of the input array.\n */\nexport declare type DeterministicSortComparator = (a: DocType, b: DocType) => 1 | -1;\n\n/**\n * To test a storage, we need these\n * configuration values.\n */\nexport type RxTestStorage = {\n // can be used to setup async stuff\n readonly init?: () => any;\n // TODO remove name here, it can be read out already via getStorage().name\n readonly name: string;\n readonly getStorage: () => RxStorage;\n /**\n * Returns a storage that is used in performance tests.\n * For example in a browser it should return the storage with an IndexedDB based adapter,\n * while in node.js it must use the filesystem.\n */\n readonly getPerformanceStorage: () => {\n storage: RxStorage;\n /**\n * A description that describes the storage and setting.\n * For example 'dexie-native'.\n */\n description: string;\n };\n /**\n * True if the storage is able to\n * keep data after an instance is closed and opened again.\n */\n readonly hasPersistence: boolean;\n readonly hasMultiInstance: boolean;\n readonly hasAttachments: boolean;\n\n /**\n * Some storages likes the memory-synced storage,\n * are not able to provide a replication while guaranteeing\n * data integrity.\n */\n readonly hasReplication: boolean;\n\n /**\n * To make it possible to test alternative encryption plugins,\n * you can specify hasEncryption to signal\n * the test runner that the given storage already contains an\n * encryption plugin that should be used to test encryption tests.\n * Otherwise the encryption-crypto-js plugin will be tested.\n *\n * hasEncryption must contain a function that is able\n * to create a new password.\n */\n readonly hasEncryption?: () => Promise;\n};\n\n\n/**\n * The paths as strings-type of nested object\n * @link https://stackoverflow.com/a/58436959/3443137\n */\ntype Join = K extends string | number ?\n P extends string | number ?\n `${K}${'' extends P ? '' : '.'}${P}`\n : never : never;\n\nexport type Paths = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: K extends string | number ?\n `${K}` | (Paths extends infer R ? Join : never)\n : never\n }[keyof T] : '';\n\nexport type Leaves = [D] extends [never] ? never : T extends object ?\n { [K in keyof T]-?: Join> }[keyof T] : '';\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\n 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n"],"mappings":"","ignoreList":[]} \ No newline at end of file diff --git a/dist/types/types/rx-document.d.ts b/dist/types/types/rx-document.d.ts index 4e9861a8ba9..f9baffc144c 100644 --- a/dist/types/types/rx-document.d.ts +++ b/dist/types/types/rx-document.d.ts @@ -57,11 +57,21 @@ export type RxDocumentMeta = { */ lwt: number; + /** + * The replication plugins "tags" the origin + * of writes to later know if a write came from + * the replication or was done locally. + */ + o?: { + hash: string; + _rev: number; + }; + /** * Any other value can be attached to the _meta data. * Mostly done by plugins to mark documents. */ - [k: string]: PlainJsonValue; + [k: string]: PlainJsonValue | undefined; }; export declare interface RxDocumentBase { diff --git a/dist/types/types/util.d.ts b/dist/types/types/util.d.ts index 2a9dbdbb495..b00f88e5c5e 100644 --- a/dist/types/types/util.d.ts +++ b/dist/types/types/util.d.ts @@ -3,7 +3,14 @@ import type { RxStorage } from './rx-storage.interface'; export type MaybePromise = Promise | T; -export type PlainJsonValue = string | number | boolean | PlainSimpleJsonObject | PlainSimpleJsonObject[] | PlainJsonValue[]; +export type PlainJsonValue = + string | + number | + boolean | + PlainSimpleJsonObject | + PlainSimpleJsonObject[] | + PlainJsonValue[] | + { [key: string]: PlainJsonValue; }; export type PlainSimpleJsonObject = { [k: string]: PlainJsonValue | PlainJsonValue[]; };