diff --git a/packages/firestore/src/local/indexeddb_mutation_queue.ts b/packages/firestore/src/local/indexeddb_mutation_queue.ts index 285b66c0de2..b015a8f304f 100644 --- a/packages/firestore/src/local/indexeddb_mutation_queue.ts +++ b/packages/firestore/src/local/indexeddb_mutation_queue.ts @@ -42,7 +42,11 @@ import { DbMutationQueue, DbMutationQueueKey } from './indexeddb_schema'; -import { LocalSerializer } from './local_serializer'; +import { + fromDbMutationBatch, + LocalSerializer, + toDbMutationBatch +} from './local_serializer'; import { MutationQueue } from './mutation_queue'; import { PersistenceTransaction, ReferenceDelegate } from './persistence'; import { PersistencePromise } from './persistence_promise'; @@ -148,7 +152,7 @@ export class IndexedDbMutationQueue implements MutationQueue { baseMutations, mutations ); - const dbBatch = this.serializer.toDbMutationBatch(this.userId, batch); + const dbBatch = toDbMutationBatch(this.serializer, this.userId, batch); const promises: Array> = []; let collectionParents = new SortedSet((l, r) => @@ -193,7 +197,7 @@ export class IndexedDbMutationQueue implements MutationQueue { dbBatch.userId === this.userId, `Unexpected user '${dbBatch.userId}' for mutation batch ${batchId}` ); - return this.serializer.fromDbMutationBatch(dbBatch); + return fromDbMutationBatch(this.serializer, dbBatch); } return null; }); @@ -244,7 +248,7 @@ export class IndexedDbMutationQueue implements MutationQueue { dbBatch.batchId >= nextBatchId, 'Should have found mutation after ' + nextBatchId ); - foundBatch = this.serializer.fromDbMutationBatch(dbBatch); + foundBatch = fromDbMutationBatch(this.serializer, dbBatch); } control.done(); } @@ -282,7 +286,7 @@ export class IndexedDbMutationQueue implements MutationQueue { return mutationsStore(transaction) .loadAll(DbMutationBatch.userMutationsIndex, range) .next(dbBatches => - dbBatches.map(dbBatch => this.serializer.fromDbMutationBatch(dbBatch)) + dbBatches.map(dbBatch => fromDbMutationBatch(this.serializer, dbBatch)) ); } @@ -331,7 +335,7 @@ export class IndexedDbMutationQueue implements MutationQueue { mutation.userId === this.userId, `Unexpected user '${mutation.userId}' for mutation batch ${batchId}` ); - results.push(this.serializer.fromDbMutationBatch(mutation)); + results.push(fromDbMutationBatch(this.serializer, mutation)); }); }) .next(() => results); @@ -462,7 +466,7 @@ export class IndexedDbMutationQueue implements MutationQueue { mutation.userId === this.userId, `Unexpected user '${mutation.userId}' for mutation batch ${batchId}` ); - results.push(this.serializer.fromDbMutationBatch(mutation)); + results.push(fromDbMutationBatch(this.serializer, mutation)); }) ); }); diff --git a/packages/firestore/src/local/indexeddb_remote_document_cache.ts b/packages/firestore/src/local/indexeddb_remote_document_cache.ts index c34ca19587e..2d11b9e258a 100644 --- a/packages/firestore/src/local/indexeddb_remote_document_cache.ts +++ b/packages/firestore/src/local/indexeddb_remote_document_cache.ts @@ -44,7 +44,13 @@ import { DbRemoteDocumentGlobalKey, DbRemoteDocumentKey } from './indexeddb_schema'; -import { LocalSerializer } from './local_serializer'; +import { + fromDbRemoteDocument, + fromDbTimestampKey, + LocalSerializer, + toDbRemoteDocument, + toDbTimestampKey +} from './local_serializer'; import { PersistenceTransaction } from './persistence'; import { PersistencePromise } from './persistence_promise'; import { RemoteDocumentCache } from './remote_document_cache'; @@ -262,7 +268,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { // since all document changes to queries that have a // lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read time set. const collectionKey = query.path.toArray(); - const readTimeKey = this.serializer.toDbTimestampKey(sinceReadTime); + const readTimeKey = toDbTimestampKey(sinceReadTime); iterationOptions.range = IDBKeyRange.lowerBound( [collectionKey, readTimeKey], /* open= */ true @@ -281,7 +287,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { return; } - const maybeDoc = this.serializer.fromDbRemoteDocument(dbRemoteDoc); + const maybeDoc = fromDbRemoteDocument(this.serializer, dbRemoteDoc); if (!query.path.isPrefixOf(maybeDoc.key.path)) { control.done(); } else if (maybeDoc instanceof Document && query.matches(maybeDoc)) { @@ -305,7 +311,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { }> { let changedDocs = maybeDocumentMap(); - let lastReadTime = this.serializer.toDbTimestampKey(sinceReadTime); + let lastReadTime = toDbTimestampKey(sinceReadTime); const documentsStore = remoteDocumentsStore(transaction); const range = IDBKeyRange.lowerBound(lastReadTime, true); @@ -315,7 +321,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { (_, dbRemoteDoc) => { // Unlike `getEntry()` and others, `getNewDocumentChanges()` parses // the documents directly since we want to keep sentinel deletes. - const doc = this.serializer.fromDbRemoteDocument(dbRemoteDoc); + const doc = fromDbRemoteDocument(this.serializer, dbRemoteDoc); changedDocs = changedDocs.insert(doc.key, doc); lastReadTime = dbRemoteDoc.readTime!; } @@ -323,7 +329,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { .next(() => { return { changedDocs, - readTime: this.serializer.fromDbTimestampKey(lastReadTime) + readTime: fromDbTimestampKey(lastReadTime) }; }); } @@ -346,7 +352,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { { index: DbRemoteDocument.readTimeIndex, reverse: true }, (key, dbRemoteDoc, control) => { if (dbRemoteDoc.readTime) { - readTime = this.serializer.fromDbTimestampKey(dbRemoteDoc.readTime); + readTime = fromDbTimestampKey(dbRemoteDoc.readTime); } control.done(); } @@ -393,7 +399,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { dbRemoteDoc: DbRemoteDocument | null ): MaybeDocument | null { if (dbRemoteDoc) { - const doc = this.serializer.fromDbRemoteDocument(dbRemoteDoc); + const doc = fromDbRemoteDocument(this.serializer, dbRemoteDoc); if ( doc instanceof NoDocument && doc.version.isEqual(SnapshotVersion.min()) @@ -456,7 +462,8 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { !this.readTime.isEqual(SnapshotVersion.min()), 'Cannot add a document with a read time of zero' ); - const doc = this.documentCache.serializer.toDbRemoteDocument( + const doc = toDbRemoteDocument( + this.documentCache.serializer, maybeDocument, this.readTime ); @@ -472,7 +479,8 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { // RemoteDocumentCache. This entry is represented by a NoDocument // with a version of 0 and ignored by `maybeDecodeDocument()` but // preserved in `getNewDocumentChanges()`. - const deletedDoc = this.documentCache.serializer.toDbRemoteDocument( + const deletedDoc = toDbRemoteDocument( + this.documentCache.serializer, new NoDocument(key, SnapshotVersion.min()), this.readTime ); diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index d091bfec9e9..0f8d9ade4e7 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -18,18 +18,23 @@ import { BatchId, ListenSequenceNumber, TargetId } from '../core/types'; import { ResourcePath } from '../model/path'; import * as api from '../protos/firestore_proto_api'; -import { hardAssert, debugAssert } from '../util/assert'; +import { debugAssert, hardAssert } from '../util/assert'; import { SnapshotVersion } from '../core/snapshot_version'; import { BATCHID_UNKNOWN } from '../model/mutation_batch'; import { decodeResourcePath, - encodeResourcePath, - EncodedResourcePath + EncodedResourcePath, + encodeResourcePath } from './encoded_resource_path'; import { removeMutationBatch } from './indexeddb_mutation_queue'; import { dbDocumentSize } from './indexeddb_remote_document_cache'; -import { LocalSerializer } from './local_serializer'; +import { + fromDbMutationBatch, + fromDbTarget, + LocalSerializer, + toDbTarget +} from './local_serializer'; import { MemoryCollectionParentIndex } from './memory_index_manager'; import { PersistencePromise } from './persistence_promise'; import { SimpleDbSchemaConverter, SimpleDbTransaction } from './simple_db'; @@ -202,7 +207,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { dbBatch.userId === queue.userId, `Cannot process batch ${dbBatch.batchId} from unexpected user` ); - const batch = this.serializer.fromDbMutationBatch(dbBatch); + const batch = fromDbMutationBatch(this.serializer, dbBatch); return removeMutationBatch( txn, @@ -324,8 +329,8 @@ export class SchemaConverter implements SimpleDbSchemaConverter { ): PersistencePromise { const targetStore = txn.store(DbTarget.store); return targetStore.iterate((key, originalDbTarget) => { - const originalTargetData = this.serializer.fromDbTarget(originalDbTarget); - const updatedDbTarget = this.serializer.toDbTarget(originalTargetData); + const originalTargetData = fromDbTarget(originalDbTarget); + const updatedDbTarget = toDbTarget(this.serializer, originalTargetData); return targetStore.put(updatedDbTarget); }); } diff --git a/packages/firestore/src/local/indexeddb_target_cache.ts b/packages/firestore/src/local/indexeddb_target_cache.ts index 24b091aa861..299c7c1844e 100644 --- a/packages/firestore/src/local/indexeddb_target_cache.ts +++ b/packages/firestore/src/local/indexeddb_target_cache.ts @@ -39,7 +39,7 @@ import { DbTargetGlobalKey, DbTargetKey } from './indexeddb_schema'; -import { LocalSerializer } from './local_serializer'; +import { fromDbTarget, LocalSerializer, toDbTarget } from './local_serializer'; import { ActiveTargets } from './lru_garbage_collector'; import { PersistenceTransaction } from './persistence'; import { PersistencePromise } from './persistence_promise'; @@ -162,7 +162,7 @@ export class IndexedDbTargetCache implements TargetCache { const promises: Array> = []; return targetsStore(txn) .iterate((key, value) => { - const targetData = this.serializer.fromDbTarget(value); + const targetData = fromDbTarget(value); if ( targetData.sequenceNumber <= upperBound && activeTargetIds.get(targetData.targetId) === null @@ -183,7 +183,7 @@ export class IndexedDbTargetCache implements TargetCache { f: (q: TargetData) => void ): PersistencePromise { return targetsStore(txn).iterate((key, value) => { - const targetData = this.serializer.fromDbTarget(value); + const targetData = fromDbTarget(value); f(targetData); }); } @@ -211,7 +211,7 @@ export class IndexedDbTargetCache implements TargetCache { targetData: TargetData ): PersistencePromise { return targetsStore(transaction).put( - this.serializer.toDbTarget(targetData) + toDbTarget(this.serializer, targetData) ); } @@ -262,7 +262,7 @@ export class IndexedDbTargetCache implements TargetCache { .iterate( { range, index: DbTarget.queryTargetsIndexName }, (key, value, control) => { - const found = this.serializer.fromDbTarget(value); + const found = fromDbTarget(value); // After finding a potential match, check that the target is // actually equal to the requested target. if (targetEquals(target, found.target)) { @@ -392,7 +392,7 @@ export class IndexedDbTargetCache implements TargetCache { .get(targetId) .next(found => { if (found) { - return this.serializer.fromDbTarget(found); + return fromDbTarget(found); } else { return null; } diff --git a/packages/firestore/src/local/local_serializer.ts b/packages/firestore/src/local/local_serializer.ts index 720534facee..1d90066dc48 100644 --- a/packages/firestore/src/local/local_serializer.ts +++ b/packages/firestore/src/local/local_serializer.ts @@ -54,194 +54,215 @@ import { TargetData, TargetPurpose } from './target_data'; /** Serializer for values stored in the LocalStore. */ export class LocalSerializer { - constructor(private remoteSerializer: JsonProtoSerializer) {} - - /** Decodes a remote document from storage locally to a Document. */ - fromDbRemoteDocument(remoteDoc: DbRemoteDocument): MaybeDocument { - if (remoteDoc.document) { - return fromDocument( - this.remoteSerializer, - remoteDoc.document, - !!remoteDoc.hasCommittedMutations - ); - } else if (remoteDoc.noDocument) { - const key = DocumentKey.fromSegments(remoteDoc.noDocument.path); - const version = this.fromDbTimestamp(remoteDoc.noDocument.readTime); - return new NoDocument(key, version, { - hasCommittedMutations: !!remoteDoc.hasCommittedMutations - }); - } else if (remoteDoc.unknownDocument) { - const key = DocumentKey.fromSegments(remoteDoc.unknownDocument.path); - const version = this.fromDbTimestamp(remoteDoc.unknownDocument.version); - return new UnknownDocument(key, version); - } else { - return fail('Unexpected DbRemoteDocument'); - } - } - - /** Encodes a document for storage locally. */ - toDbRemoteDocument( - maybeDoc: MaybeDocument, - readTime: SnapshotVersion - ): DbRemoteDocument { - const dbReadTime = this.toDbTimestampKey(readTime); - const parentPath = maybeDoc.key.path.popLast().toArray(); - if (maybeDoc instanceof Document) { - const doc = toDocument(this.remoteSerializer, maybeDoc); - const hasCommittedMutations = maybeDoc.hasCommittedMutations; - return new DbRemoteDocument( - /* unknownDocument= */ null, - /* noDocument= */ null, - doc, - hasCommittedMutations, - dbReadTime, - parentPath - ); - } else if (maybeDoc instanceof NoDocument) { - const path = maybeDoc.key.path.toArray(); - const readTime = this.toDbTimestamp(maybeDoc.version); - const hasCommittedMutations = maybeDoc.hasCommittedMutations; - return new DbRemoteDocument( - /* unknownDocument= */ null, - new DbNoDocument(path, readTime), - /* document= */ null, - hasCommittedMutations, - dbReadTime, - parentPath - ); - } else if (maybeDoc instanceof UnknownDocument) { - const path = maybeDoc.key.path.toArray(); - const readTime = this.toDbTimestamp(maybeDoc.version); - return new DbRemoteDocument( - new DbUnknownDocument(path, readTime), - /* noDocument= */ null, - /* document= */ null, - /* hasCommittedMutations= */ true, - dbReadTime, - parentPath - ); - } else { - return fail('Unexpected MaybeDocument'); - } - } - - toDbTimestampKey(snapshotVersion: SnapshotVersion): DbTimestampKey { - const timestamp = snapshotVersion.toTimestamp(); - return [timestamp.seconds, timestamp.nanoseconds]; - } - - fromDbTimestampKey(dbTimestampKey: DbTimestampKey): SnapshotVersion { - const timestamp = new Timestamp(dbTimestampKey[0], dbTimestampKey[1]); - return SnapshotVersion.fromTimestamp(timestamp); - } - - private toDbTimestamp(snapshotVersion: SnapshotVersion): DbTimestamp { - const timestamp = snapshotVersion.toTimestamp(); - return new DbTimestamp(timestamp.seconds, timestamp.nanoseconds); - } + constructor(readonly remoteSerializer: JsonProtoSerializer) {} +} - private fromDbTimestamp(dbTimestamp: DbTimestamp): SnapshotVersion { - const timestamp = new Timestamp( - dbTimestamp.seconds, - dbTimestamp.nanoseconds +/** Decodes a remote document from storage locally to a Document. */ +export function fromDbRemoteDocument( + localSerializer: LocalSerializer, + remoteDoc: DbRemoteDocument +): MaybeDocument { + if (remoteDoc.document) { + return fromDocument( + localSerializer.remoteSerializer, + remoteDoc.document, + !!remoteDoc.hasCommittedMutations ); - return SnapshotVersion.fromTimestamp(timestamp); + } else if (remoteDoc.noDocument) { + const key = DocumentKey.fromSegments(remoteDoc.noDocument.path); + const version = fromDbTimestamp(remoteDoc.noDocument.readTime); + return new NoDocument(key, version, { + hasCommittedMutations: !!remoteDoc.hasCommittedMutations + }); + } else if (remoteDoc.unknownDocument) { + const key = DocumentKey.fromSegments(remoteDoc.unknownDocument.path); + const version = fromDbTimestamp(remoteDoc.unknownDocument.version); + return new UnknownDocument(key, version); + } else { + return fail('Unexpected DbRemoteDocument'); } +} - /** Encodes a batch of mutations into a DbMutationBatch for local storage. */ - toDbMutationBatch(userId: string, batch: MutationBatch): DbMutationBatch { - const serializedBaseMutations = batch.baseMutations.map(m => - toMutation(this.remoteSerializer, m) +/** Encodes a document for storage locally. */ +export function toDbRemoteDocument( + localSerializer: LocalSerializer, + maybeDoc: MaybeDocument, + readTime: SnapshotVersion +): DbRemoteDocument { + const dbReadTime = toDbTimestampKey(readTime); + const parentPath = maybeDoc.key.path.popLast().toArray(); + if (maybeDoc instanceof Document) { + const doc = toDocument(localSerializer.remoteSerializer, maybeDoc); + const hasCommittedMutations = maybeDoc.hasCommittedMutations; + return new DbRemoteDocument( + /* unknownDocument= */ null, + /* noDocument= */ null, + doc, + hasCommittedMutations, + dbReadTime, + parentPath ); - const serializedMutations = batch.mutations.map(m => - toMutation(this.remoteSerializer, m) + } else if (maybeDoc instanceof NoDocument) { + const path = maybeDoc.key.path.toArray(); + const readTime = toDbTimestamp(maybeDoc.version); + const hasCommittedMutations = maybeDoc.hasCommittedMutations; + return new DbRemoteDocument( + /* unknownDocument= */ null, + new DbNoDocument(path, readTime), + /* document= */ null, + hasCommittedMutations, + dbReadTime, + parentPath ); - return new DbMutationBatch( - userId, - batch.batchId, - batch.localWriteTime.toMillis(), - serializedBaseMutations, - serializedMutations + } else if (maybeDoc instanceof UnknownDocument) { + const path = maybeDoc.key.path.toArray(); + const readTime = toDbTimestamp(maybeDoc.version); + return new DbRemoteDocument( + new DbUnknownDocument(path, readTime), + /* noDocument= */ null, + /* document= */ null, + /* hasCommittedMutations= */ true, + dbReadTime, + parentPath ); + } else { + return fail('Unexpected MaybeDocument'); } +} - /** Decodes a DbMutationBatch into a MutationBatch */ - fromDbMutationBatch(dbBatch: DbMutationBatch): MutationBatch { - const baseMutations = (dbBatch.baseMutations || []).map(m => - fromMutation(this.remoteSerializer, m) - ); - const mutations = dbBatch.mutations.map(m => - fromMutation(this.remoteSerializer, m) - ); - const timestamp = Timestamp.fromMillis(dbBatch.localWriteTimeMs); - return new MutationBatch( - dbBatch.batchId, - timestamp, - baseMutations, - mutations - ); - } +export function toDbTimestampKey( + snapshotVersion: SnapshotVersion +): DbTimestampKey { + const timestamp = snapshotVersion.toTimestamp(); + return [timestamp.seconds, timestamp.nanoseconds]; +} - /** Decodes a DbTarget into TargetData */ - fromDbTarget(dbTarget: DbTarget): TargetData { - const version = this.fromDbTimestamp(dbTarget.readTime); - const lastLimboFreeSnapshotVersion = - dbTarget.lastLimboFreeSnapshotVersion !== undefined - ? this.fromDbTimestamp(dbTarget.lastLimboFreeSnapshotVersion) - : SnapshotVersion.min(); - - let target: Target; - if (isDocumentQuery(dbTarget.query)) { - target = fromDocumentsTarget(dbTarget.query); - } else { - target = fromQueryTarget(dbTarget.query); - } - return new TargetData( - target, - dbTarget.targetId, - TargetPurpose.Listen, - dbTarget.lastListenSequenceNumber, - version, - lastLimboFreeSnapshotVersion, - ByteString.fromBase64String(dbTarget.resumeToken) - ); +export function fromDbTimestampKey( + dbTimestampKey: DbTimestampKey +): SnapshotVersion { + const timestamp = new Timestamp(dbTimestampKey[0], dbTimestampKey[1]); + return SnapshotVersion.fromTimestamp(timestamp); +} + +function toDbTimestamp(snapshotVersion: SnapshotVersion): DbTimestamp { + const timestamp = snapshotVersion.toTimestamp(); + return new DbTimestamp(timestamp.seconds, timestamp.nanoseconds); +} + +function fromDbTimestamp(dbTimestamp: DbTimestamp): SnapshotVersion { + const timestamp = new Timestamp(dbTimestamp.seconds, dbTimestamp.nanoseconds); + return SnapshotVersion.fromTimestamp(timestamp); +} + +/** Encodes a batch of mutations into a DbMutationBatch for local storage. */ +export function toDbMutationBatch( + localSerializer: LocalSerializer, + userId: string, + batch: MutationBatch +): DbMutationBatch { + const serializedBaseMutations = batch.baseMutations.map(m => + toMutation(localSerializer.remoteSerializer, m) + ); + const serializedMutations = batch.mutations.map(m => + toMutation(localSerializer.remoteSerializer, m) + ); + return new DbMutationBatch( + userId, + batch.batchId, + batch.localWriteTime.toMillis(), + serializedBaseMutations, + serializedMutations + ); +} + +/** Decodes a DbMutationBatch into a MutationBatch */ +export function fromDbMutationBatch( + localSerializer: LocalSerializer, + dbBatch: DbMutationBatch +): MutationBatch { + const baseMutations = (dbBatch.baseMutations || []).map(m => + fromMutation(localSerializer.remoteSerializer, m) + ); + const mutations = dbBatch.mutations.map(m => + fromMutation(localSerializer.remoteSerializer, m) + ); + const timestamp = Timestamp.fromMillis(dbBatch.localWriteTimeMs); + return new MutationBatch( + dbBatch.batchId, + timestamp, + baseMutations, + mutations + ); +} + +/** Decodes a DbTarget into TargetData */ +export function fromDbTarget(dbTarget: DbTarget): TargetData { + const version = fromDbTimestamp(dbTarget.readTime); + const lastLimboFreeSnapshotVersion = + dbTarget.lastLimboFreeSnapshotVersion !== undefined + ? fromDbTimestamp(dbTarget.lastLimboFreeSnapshotVersion) + : SnapshotVersion.min(); + + let target: Target; + if (isDocumentQuery(dbTarget.query)) { + target = fromDocumentsTarget(dbTarget.query); + } else { + target = fromQueryTarget(dbTarget.query); } + return new TargetData( + target, + dbTarget.targetId, + TargetPurpose.Listen, + dbTarget.lastListenSequenceNumber, + version, + lastLimboFreeSnapshotVersion, + ByteString.fromBase64String(dbTarget.resumeToken) + ); +} - /** Encodes TargetData into a DbTarget for storage locally. */ - toDbTarget(targetData: TargetData): DbTarget { - debugAssert( - TargetPurpose.Listen === targetData.purpose, - 'Only queries with purpose ' + - TargetPurpose.Listen + - ' may be stored, got ' + - targetData.purpose - ); - const dbTimestamp = this.toDbTimestamp(targetData.snapshotVersion); - const dbLastLimboFreeTimestamp = this.toDbTimestamp( - targetData.lastLimboFreeSnapshotVersion +/** Encodes TargetData into a DbTarget for storage locally. */ +export function toDbTarget( + localSerializer: LocalSerializer, + targetData: TargetData +): DbTarget { + debugAssert( + TargetPurpose.Listen === targetData.purpose, + 'Only queries with purpose ' + + TargetPurpose.Listen + + ' may be stored, got ' + + targetData.purpose + ); + const dbTimestamp = toDbTimestamp(targetData.snapshotVersion); + const dbLastLimboFreeTimestamp = toDbTimestamp( + targetData.lastLimboFreeSnapshotVersion + ); + let queryProto: DbQuery; + if (isDocumentTarget(targetData.target)) { + queryProto = toDocumentsTarget( + localSerializer.remoteSerializer, + targetData.target ); - let queryProto: DbQuery; - if (isDocumentTarget(targetData.target)) { - queryProto = toDocumentsTarget(this.remoteSerializer, targetData.target); - } else { - queryProto = toQueryTarget(this.remoteSerializer, targetData.target); - } - - // We can't store the resumeToken as a ByteString in IndexedDb, so we - // convert it to a base64 string for storage. - const resumeToken = targetData.resumeToken.toBase64(); - - // lastListenSequenceNumber is always 0 until we do real GC. - return new DbTarget( - targetData.targetId, - canonifyTarget(targetData.target), - dbTimestamp, - resumeToken, - targetData.sequenceNumber, - dbLastLimboFreeTimestamp, - queryProto + } else { + queryProto = toQueryTarget( + localSerializer.remoteSerializer, + targetData.target ); } + + // We can't store the resumeToken as a ByteString in IndexedDb, so we + // convert it to a base64 string for storage. + const resumeToken = targetData.resumeToken.toBase64(); + + // lastListenSequenceNumber is always 0 until we do real GC. + return new DbTarget( + targetData.targetId, + canonifyTarget(targetData.target), + dbTimestamp, + resumeToken, + targetData.sequenceNumber, + dbLastLimboFreeTimestamp, + queryProto + ); } /** diff --git a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts index 02bddb52515..c933b32b3fb 100644 --- a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts +++ b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts @@ -73,6 +73,12 @@ import { TEST_PERSISTENCE_PREFIX, TEST_SERIALIZER } from './persistence_test_helpers'; +import { + fromDbTarget, + toDbRemoteDocument, + toDbTarget, + toDbTimestampKey +} from '../../../src/local/local_serializer'; import { canonifyTarget } from '../../../src/core/target'; import { FakeDocument, testDocument } from '../../util/test_platform'; import { getWindow } from '../../../src/platform/dom'; @@ -235,7 +241,8 @@ function addDocs( ); return PersistencePromise.forEach(keys, (key: string) => { const remoteDoc = doc(key, version, { data: 'foo' }); - const dbRemoteDoc = TEST_SERIALIZER.toDbRemoteDocument( + const dbRemoteDoc = toDbRemoteDocument( + TEST_SERIALIZER, remoteDoc, remoteDoc.version ); @@ -579,7 +586,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { ]; const dbRemoteDocs = docs.map(doc => ({ dbKey: doc.key.path.toArray(), - dbDoc: TEST_SERIALIZER.toDbRemoteDocument(doc, doc.version) + dbDoc: toDbRemoteDocument(TEST_SERIALIZER, doc, doc.version) })); // V5 stores doesn't exist const sdb = new SimpleDb(db); @@ -647,7 +654,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { promises.push( remoteDocumentStore.put( document.key.path.toArray(), - serializer.toDbRemoteDocument(document, document.version) + toDbRemoteDocument(serializer, document, document.version) ) ); if (i % 2 === 1) { @@ -748,7 +755,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const remoteDoc = doc(path, /*version=*/ 1, { data: 1 }); return remoteDocumentStore.put( remoteDoc.key.path.toArray(), - TEST_SERIALIZER.toDbRemoteDocument(remoteDoc, remoteDoc.version) + toDbRemoteDocument(TEST_SERIALIZER, remoteDoc, remoteDoc.version) ); }); }); @@ -796,10 +803,10 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { /* sequenceNumber= */ 1 ); - const serializedData = TEST_SERIALIZER.toDbTarget(initialTargetData); + const serializedData = toDbTarget(TEST_SERIALIZER, initialTargetData); serializedData.canonicalId = 'invalid_canonical_id'; - return targetsStore.put(TEST_SERIALIZER.toDbTarget(initialTargetData)); + return targetsStore.put(toDbTarget(TEST_SERIALIZER, initialTargetData)); }); }); @@ -808,7 +815,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { return sdb.runTransaction('readwrite', V8_STORES, txn => { const targetsStore = txn.store(DbTarget.store); return targetsStore.iterate((key, value) => { - const targetData = TEST_SERIALIZER.fromDbTarget(value).target; + const targetData = fromDbTarget(value).target; const expectedCanonicalId = canonifyTarget(targetData); const actualCanonicalId = value.canonicalId; @@ -848,7 +855,8 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { return PersistencePromise.forEach(existingDocPaths, (path: string) => { const remoteDoc = doc(path, /*version=*/ 1, { data: 1 }); - const dbRemoteDoc = TEST_SERIALIZER.toDbRemoteDocument( + const dbRemoteDoc = toDbRemoteDocument( + TEST_SERIALIZER, remoteDoc, remoteDoc.version ); @@ -889,7 +897,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { .next(() => { // Verify that we can get recent changes in a collection filtered by // read time. - const lastReadTime = TEST_SERIALIZER.toDbTimestampKey(version(1)); + const lastReadTime = toDbTimestampKey(version(1)); const range = IDBKeyRange.lowerBound( [['coll2'], lastReadTime], true @@ -922,7 +930,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbRemoteDocument >(DbRemoteDocument.store); - const lastReadTime = TEST_SERIALIZER.toDbTimestampKey(version(1)); + const lastReadTime = toDbTimestampKey(version(1)); const range = IDBKeyRange.lowerBound( [['coll'], lastReadTime], true @@ -956,7 +964,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbRemoteDocument >(DbRemoteDocument.store); - const lastReadTime = TEST_SERIALIZER.toDbTimestampKey(version(1)); + const lastReadTime = toDbTimestampKey(version(1)); const range = IDBKeyRange.lowerBound(lastReadTime, true); return remoteDocumentStore .loadAll(DbRemoteDocument.readTimeIndex, range)