diff --git a/packages/firestore/src/core/component_provider.ts b/packages/firestore/src/core/component_provider.ts index 2c34723ecef..285b9e66ac0 100644 --- a/packages/firestore/src/core/component_provider.ts +++ b/packages/firestore/src/core/component_provider.ts @@ -162,6 +162,7 @@ export class MemoryComponentProvider implements ComponentProvider { return new SyncEngine( this.localStore, this.remoteStore, + cfg.datastore, this.sharedClientState, cfg.initialUser, cfg.maxConcurrentLimboResolutions @@ -219,6 +220,7 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider { const syncEngine = new MultiTabSyncEngine( this.localStore, this.remoteStore, + cfg.datastore, this.sharedClientState, cfg.initialUser, cfg.maxConcurrentLimboResolutions diff --git a/packages/firestore/src/core/sync_engine.ts b/packages/firestore/src/core/sync_engine.ts index 0204f403e50..0286c2c079f 100644 --- a/packages/firestore/src/core/sync_engine.ts +++ b/packages/firestore/src/core/sync_engine.ts @@ -74,6 +74,7 @@ import { import { ViewSnapshot } from './view_snapshot'; import { AsyncQueue, wrapInUserErrorIfRecoverable } from '../util/async_queue'; import { TransactionRunner } from './transaction_runner'; +import { Datastore } from '../remote/datastore'; const LOG_TAG = 'SyncEngine'; @@ -185,6 +186,7 @@ export class SyncEngine implements RemoteSyncer { constructor( protected localStore: LocalStore, protected remoteStore: RemoteStore, + protected datastore: Datastore, // PORTING NOTE: Manages state synchronization in multi-tab environments. protected sharedClientState: SharedClientState, private currentUser: User, @@ -390,7 +392,7 @@ export class SyncEngine implements RemoteSyncer { ): void { new TransactionRunner( asyncQueue, - this.remoteStore, + this.datastore, updateFunction, deferred ).run(); @@ -924,6 +926,7 @@ export class MultiTabSyncEngine extends SyncEngine constructor( protected localStore: MultiTabLocalStore, remoteStore: RemoteStore, + datastore: Datastore, sharedClientState: SharedClientState, currentUser: User, maxConcurrentLimboResolutions: number @@ -931,6 +934,7 @@ export class MultiTabSyncEngine extends SyncEngine super( localStore, remoteStore, + datastore, sharedClientState, currentUser, maxConcurrentLimboResolutions diff --git a/packages/firestore/src/core/transaction.ts b/packages/firestore/src/core/transaction.ts index 39f380c7950..0beefda0bf5 100644 --- a/packages/firestore/src/core/transaction.ts +++ b/packages/firestore/src/core/transaction.ts @@ -16,7 +16,6 @@ */ import { ParsedSetData, ParsedUpdateData } from '../api/user_data_reader'; -import { documentVersionMap } from '../model/collections'; import { Document, MaybeDocument, NoDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; @@ -34,6 +33,7 @@ import { import { fail, debugAssert } from '../util/assert'; import { Code, FirestoreError } from '../util/error'; import { SnapshotVersion } from './snapshot_version'; +import { ResourcePath } from '../model/path'; /** * Internal transaction object responsible for accumulating the mutations to @@ -41,7 +41,7 @@ import { SnapshotVersion } from './snapshot_version'; */ export class Transaction { // The version of each document that was read during this transaction. - private readVersions = documentVersionMap(); + private readVersions = new Map(); private mutations: Mutation[] = []; private committed = false; @@ -106,14 +106,15 @@ export class Transaction { if (this.lastWriteError) { throw this.lastWriteError; } - let unwritten = this.readVersions; + const unwritten = this.readVersions; // For each mutation, note that the doc was written. this.mutations.forEach(mutation => { - unwritten = unwritten.remove(mutation.key); + unwritten.delete(mutation.key.toString()); }); // For each document that was read but not written to, we want to perform // a `verify` operation. - unwritten.forEach((key, _version) => { + unwritten.forEach((_, path) => { + const key = new DocumentKey(ResourcePath.fromString(path)); this.mutations.push(new VerifyMutation(key, this.precondition(key))); }); await invokeCommitRpc(this.datastore, this.mutations); @@ -132,8 +133,8 @@ export class Transaction { throw fail('Document in a transaction was a ' + doc.constructor.name); } - const existingVersion = this.readVersions.get(doc.key); - if (existingVersion !== null) { + const existingVersion = this.readVersions.get(doc.key.toString()); + if (existingVersion) { if (!docVersion.isEqual(existingVersion)) { // This transaction will fail no matter what. throw new FirestoreError( @@ -142,7 +143,7 @@ export class Transaction { ); } } else { - this.readVersions = this.readVersions.insert(doc.key, docVersion); + this.readVersions.set(doc.key.toString(), docVersion); } } @@ -151,7 +152,7 @@ export class Transaction { * as a precondition, or no precondition if it was not read. */ private precondition(key: DocumentKey): Precondition { - const version = this.readVersions.get(key); + const version = this.readVersions.get(key.toString()); if (!this.writtenDocs.has(key) && version) { return Precondition.updateTime(version); } else { @@ -163,7 +164,7 @@ export class Transaction { * Returns the precondition for a document if the operation is an update. */ private preconditionForUpdate(key: DocumentKey): Precondition { - const version = this.readVersions.get(key); + const version = this.readVersions.get(key.toString()); // The first time a document is written, we want to take into account the // read time and existence if (!this.writtenDocs.has(key) && version) { diff --git a/packages/firestore/src/core/transaction_runner.ts b/packages/firestore/src/core/transaction_runner.ts index 1c0a16acdd0..9a5879af168 100644 --- a/packages/firestore/src/core/transaction_runner.ts +++ b/packages/firestore/src/core/transaction_runner.ts @@ -19,7 +19,7 @@ import { Deferred } from '../util/promise'; import { TimerId, AsyncQueue } from '../util/async_queue'; import { ExponentialBackoff } from '../remote/backoff'; import { Transaction } from './transaction'; -import { RemoteStore } from '../remote/remote_store'; +import { Datastore } from '../remote/datastore'; import { isNullOrUndefined } from '../util/types'; import { isPermanentError } from '../remote/rpc_error'; import { FirestoreError } from '../util/error'; @@ -36,7 +36,7 @@ export class TransactionRunner { constructor( private readonly asyncQueue: AsyncQueue, - private readonly remoteStore: RemoteStore, + private readonly datastore: Datastore, private readonly updateFunction: (transaction: Transaction) => Promise, private readonly deferred: Deferred ) { @@ -53,7 +53,7 @@ export class TransactionRunner { private runWithBackOff(): void { this.backoff.backoffAndRun(async () => { - const transaction = this.remoteStore.createTransaction(); + const transaction = new Transaction(this.datastore); const userPromise = this.tryRunUpdateFunction(transaction); if (userPromise) { userPromise