Skip to content

Commit 05fe956

Browse files
Adding CommitVersion to RemoteDocumentCache
1 parent 7d9f111 commit 05fe956

19 files changed

+275
-151
lines changed

packages/firestore/src/core/transaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class Transaction {
3737
constructor(private datastore: Datastore) {}
3838

3939
private recordVersion(doc: MaybeDocument): void {
40-
let docVersion = doc.version;
40+
let docVersion = doc.remoteVersion;
4141
if (doc instanceof NoDocument) {
4242
// For deleted docs, we must use baseVersion 0 when we overwrite them.
4343
docVersion = SnapshotVersion.forDeletedDoc();

packages/firestore/src/local/indexeddb_schema.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,14 @@ export class DbRemoteDocument {
446446
* Set to an instance of a Document if there's a cached version of the
447447
* document.
448448
*/
449-
public document: api.Document | null
449+
public document: api.Document | null,
450+
/**
451+
* For documents that were written to the remote document store based on
452+
* a write acknowledgment, we store the commit version of the mutation. This
453+
* is used to determine if the document is 'dirty' (the commit version is
454+
* higher than `document.updateTime`).
455+
*/
456+
public commitVersion?: DbTimestamp
450457
) {}
451458
}
452459

packages/firestore/src/local/local_serializer.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ export class LocalSerializer {
4343
/** Decodes a remote document from storage locally to a Document. */
4444
fromDbRemoteDocument(remoteDoc: DbRemoteDocument): MaybeDocument {
4545
if (remoteDoc.document) {
46-
return this.remoteSerializer.fromDocument(remoteDoc.document);
46+
const commitTime = this.fromDbTimestamp(remoteDoc.commitVersion);
47+
return this.remoteSerializer.fromDocument(remoteDoc.document, commitTime);
4748
} else if (remoteDoc.noDocument) {
4849
const key = DocumentKey.fromSegments(remoteDoc.noDocument.path);
49-
const readTime = remoteDoc.noDocument.readTime;
50-
const timestamp = new Timestamp(readTime.seconds, readTime.nanoseconds);
51-
return new NoDocument(key, SnapshotVersion.fromTimestamp(timestamp));
50+
const version = this.fromDbTimestamp(remoteDoc.noDocument.readTime);
51+
return new NoDocument(key, version);
5252
} else {
5353
return fail('Unexpected DbRemoteDocument');
5454
}
@@ -57,19 +57,33 @@ export class LocalSerializer {
5757
/** Encodes a document for storage locally. */
5858
toDbRemoteDocument(maybeDoc: MaybeDocument): DbRemoteDocument {
5959
if (maybeDoc instanceof Document) {
60+
const commitVersion = this.toDbTimestamp(maybeDoc.commitVersion);
6061
const doc = this.remoteSerializer.toDocument(maybeDoc);
61-
return new DbRemoteDocument(null, doc);
62+
return new DbRemoteDocument(null, doc, commitVersion);
6263
} else {
6364
const path = maybeDoc.key.path.toArray();
64-
const timestamp = maybeDoc.version.toTimestamp();
65-
const readTime = new DbTimestamp(
66-
timestamp.seconds,
67-
timestamp.nanoseconds
68-
);
65+
const readTime = this.toDbTimestamp(maybeDoc.remoteVersion);
6966
return new DbRemoteDocument(new DbNoDocument(path, readTime), null);
7067
}
7168
}
7269

70+
private toDbTimestamp(snapshotVersion: SnapshotVersion): DbTimestamp {
71+
const timestamp = snapshotVersion.toTimestamp();
72+
return new DbTimestamp(timestamp.seconds, timestamp.nanoseconds);
73+
}
74+
75+
private fromDbTimestamp(dbTimestamp?: DbTimestamp): SnapshotVersion {
76+
if (dbTimestamp) {
77+
const timestamp = new Timestamp(
78+
dbTimestamp.seconds,
79+
dbTimestamp.nanoseconds
80+
);
81+
return SnapshotVersion.fromTimestamp(timestamp);
82+
} else {
83+
return SnapshotVersion.MIN;
84+
}
85+
}
86+
7387
/** Encodes a batch of mutations into a DbMutationBatch for local storage. */
7488
toDbMutationBatch(userId: string, batch: MutationBatch): DbMutationBatch {
7589
const serializedMutations = batch.mutations.map(m =>
@@ -118,11 +132,7 @@ export class LocalSerializer {
118132

119133
/** Decodes a DbTarget into QueryData */
120134
fromDbTarget(dbTarget: DbTarget): QueryData {
121-
const readTime = new Timestamp(
122-
dbTarget.readTime.seconds,
123-
dbTarget.readTime.nanoseconds
124-
);
125-
const version = SnapshotVersion.fromTimestamp(readTime);
135+
const version = this.fromDbTimestamp(dbTarget.readTime);
126136
let query: Query;
127137
if (isDocumentQuery(dbTarget.query)) {
128138
query = this.remoteSerializer.fromDocumentsTarget(dbTarget.query);
@@ -147,11 +157,7 @@ export class LocalSerializer {
147157
' may be stored, got ' +
148158
queryData.purpose
149159
);
150-
const timestamp = queryData.snapshotVersion.toTimestamp();
151-
const dbTimestamp = new DbTimestamp(
152-
timestamp.seconds,
153-
timestamp.nanoseconds
154-
);
160+
const dbTimestamp = this.toDbTimestamp(queryData.snapshotVersion);
155161
let queryProto: DbQuery;
156162
if (queryData.query.isDocumentQuery()) {
157163
queryProto = this.remoteSerializer.toDocumentsTarget(queryData.query);

packages/firestore/src/local/local_store.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,9 @@ export class LocalStore {
563563
// resolution failing).
564564
if (
565565
existingDoc == null ||
566-
doc.version.isEqual(SnapshotVersion.MIN) ||
566+
doc.remoteVersion.isEqual(SnapshotVersion.MIN) ||
567567
authoritativeUpdates.has(doc.key) ||
568-
doc.version.compareTo(existingDoc.version) >= 0
568+
doc.remoteVersion.compareTo(existingDoc.remoteVersion) >= 0
569569
) {
570570
documentBuffer.addEntry(doc);
571571
} else {
@@ -574,9 +574,9 @@ export class LocalStore {
574574
'Ignoring outdated watch update for ',
575575
key,
576576
'. Current version:',
577-
existingDoc.version,
577+
existingDoc.remoteVersion,
578578
' Watch version:',
579-
doc.version
579+
doc.remoteVersion
580580
);
581581
}
582582

@@ -1008,7 +1008,7 @@ export class LocalStore {
10081008
ackVersion !== null,
10091009
'ackVersions should contain every doc in the write.'
10101010
);
1011-
if (!doc || doc.version.compareTo(ackVersion!) < 0) {
1011+
if (!doc || doc.remoteVersion.compareTo(ackVersion!) < 0) {
10121012
doc = batch.applyToRemoteDocument(docKey, doc, batchResult);
10131013
if (!doc) {
10141014
assert(

packages/firestore/src/model/document.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ export interface DocumentOptions {
3131
* marker that this document does not exist at a given version.
3232
*/
3333
export abstract class MaybeDocument {
34-
constructor(readonly key: DocumentKey, readonly version: SnapshotVersion) {}
34+
constructor(
35+
readonly key: DocumentKey,
36+
readonly remoteVersion: SnapshotVersion
37+
) {}
3538

3639
static compareByKey(d1: MaybeDocument, d2: MaybeDocument): number {
3740
return DocumentKey.comparator(d1.key, d2.key);
@@ -47,11 +50,12 @@ export class Document extends MaybeDocument {
4750

4851
constructor(
4952
key: DocumentKey,
50-
version: SnapshotVersion,
53+
remoteVersion: SnapshotVersion,
54+
readonly commitVersion: SnapshotVersion,
5155
readonly data: ObjectValue,
5256
options: DocumentOptions
5357
) {
54-
super(key, version);
58+
super(key, remoteVersion);
5559
this.hasLocalMutations = options.hasLocalMutations;
5660
}
5761

@@ -72,15 +76,16 @@ export class Document extends MaybeDocument {
7276
return (
7377
other instanceof Document &&
7478
this.key.isEqual(other.key) &&
75-
this.version.isEqual(other.version) &&
79+
this.remoteVersion.isEqual(other.remoteVersion) &&
80+
this.commitVersion.isEqual(other.commitVersion) &&
7681
this.data.isEqual(other.data) &&
7782
this.hasLocalMutations === other.hasLocalMutations
7883
);
7984
}
8085

8186
toString(): string {
8287
return (
83-
`Document(${this.key}, ${this.version}, ${this.data.toString()}, ` +
88+
`Document(${this.key}, ${this.remoteVersion}, ${this.data.toString()}, ` +
8489
`{hasLocalMutations: ${this.hasLocalMutations}})`
8590
);
8691
}
@@ -102,18 +107,18 @@ export class Document extends MaybeDocument {
102107
* denotes time we know it didn't exist at.
103108
*/
104109
export class NoDocument extends MaybeDocument {
105-
constructor(key: DocumentKey, version: SnapshotVersion) {
106-
super(key, version);
110+
constructor(key: DocumentKey, remoteVersion: SnapshotVersion) {
111+
super(key, remoteVersion);
107112
}
108113

109114
toString(): string {
110-
return `NoDocument(${this.key}, ${this.version})`;
115+
return `NoDocument(${this.key}, ${this.remoteVersion})`;
111116
}
112117

113118
isEqual(other: NoDocument): boolean {
114119
return (
115120
other &&
116-
other.version.isEqual(this.version) &&
121+
other.remoteVersion.isEqual(this.remoteVersion) &&
117122
other.key.isEqual(this.key)
118123
);
119124
}

packages/firestore/src/model/mutation.ts

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ export class FieldTransform {
7979
export class MutationResult {
8080
constructor(
8181
/**
82-
* The version at which the mutation was committed or null for a delete.
82+
* The version at which the mutation was committed, either extracted from
83+
* the mutation's updateTime or from the responses commit time (for
84+
* deletes).
8385
*/
84-
readonly version: SnapshotVersion | null,
86+
readonly version: SnapshotVersion,
8587
/**
8688
* The resulting fields returned from the backend after a
8789
* TransformMutation has been committed. Contains one FieldValue for each
@@ -141,7 +143,7 @@ export class Precondition {
141143
if (this.updateTime !== undefined) {
142144
return (
143145
maybeDoc instanceof Document &&
144-
maybeDoc.version.isEqual(this.updateTime)
146+
maybeDoc.remoteVersion.isEqual(this.updateTime)
145147
);
146148
} else if (this.exists !== undefined) {
147149
if (this.exists) {
@@ -264,7 +266,7 @@ export abstract class Mutation {
264266
maybeDoc: MaybeDocument | null
265267
): SnapshotVersion {
266268
if (maybeDoc instanceof Document) {
267-
return maybeDoc.version;
269+
return maybeDoc.remoteVersion;
268270
} else {
269271
return SnapshotVersion.MIN;
270272
}
@@ -301,8 +303,9 @@ export class SetMutation extends Mutation {
301303
// document the server has accepted the mutation so the precondition must
302304
// have held.
303305

304-
const version = Mutation.getPostMutationVersion(maybeDoc);
305-
return new Document(this.key, version, this.value, {
306+
const remoteVersion = Mutation.getPostMutationVersion(maybeDoc);
307+
const commitVersion = mutationResult.version;
308+
return new Document(this.key, remoteVersion, commitVersion, this.value, {
306309
hasLocalMutations: false
307310
});
308311
}
@@ -318,10 +321,16 @@ export class SetMutation extends Mutation {
318321
return maybeDoc;
319322
}
320323

321-
const version = Mutation.getPostMutationVersion(maybeDoc);
322-
return new Document(this.key, version, this.value, {
323-
hasLocalMutations: true
324-
});
324+
const remoteVersion = Mutation.getPostMutationVersion(maybeDoc);
325+
return new Document(
326+
this.key,
327+
remoteVersion,
328+
/*commitVersion=*/ SnapshotVersion.MIN,
329+
this.value,
330+
{
331+
hasLocalMutations: true
332+
}
333+
);
325334
}
326335

327336
isEqual(other: Mutation): boolean {
@@ -380,9 +389,10 @@ export class PatchMutation extends Mutation {
380389
return maybeDoc;
381390
}
382391

383-
const version = Mutation.getPostMutationVersion(maybeDoc);
392+
const remoteVersion = Mutation.getPostMutationVersion(maybeDoc);
393+
const commitVersion = mutationResult.version;
384394
const newData = this.patchDocument(maybeDoc);
385-
return new Document(this.key, version, newData, {
395+
return new Document(this.key, remoteVersion, commitVersion, newData, {
386396
hasLocalMutations: false
387397
});
388398
}
@@ -398,11 +408,17 @@ export class PatchMutation extends Mutation {
398408
return maybeDoc;
399409
}
400410

401-
const version = Mutation.getPostMutationVersion(maybeDoc);
411+
const remoteVersion = Mutation.getPostMutationVersion(maybeDoc);
402412
const newData = this.patchDocument(maybeDoc);
403-
return new Document(this.key, version, newData, {
404-
hasLocalMutations: true
405-
});
413+
return new Document(
414+
this.key,
415+
remoteVersion,
416+
/*commitVersion=*/ SnapshotVersion.MIN,
417+
newData,
418+
{
419+
hasLocalMutations: true
420+
}
421+
);
406422
}
407423

408424
isEqual(other: Mutation): boolean {
@@ -492,8 +508,10 @@ export class TransformMutation extends Mutation {
492508
maybeDoc,
493509
mutationResult.transformResults!
494510
);
511+
const remoteVersion = Mutation.getPostMutationVersion(maybeDoc);
512+
const commitVersion = mutationResult.version;
495513
const newData = this.transformObject(doc.data, transformResults);
496-
return new Document(this.key, doc.version, newData, {
514+
return new Document(this.key, remoteVersion, commitVersion, newData, {
497515
hasLocalMutations: false
498516
});
499517
}
@@ -515,9 +533,15 @@ export class TransformMutation extends Mutation {
515533
baseDoc
516534
);
517535
const newData = this.transformObject(doc.data, transformResults);
518-
return new Document(this.key, doc.version, newData, {
519-
hasLocalMutations: true
520-
});
536+
return new Document(
537+
this.key,
538+
doc.remoteVersion,
539+
SnapshotVersion.MIN,
540+
newData,
541+
{
542+
hasLocalMutations: true
543+
}
544+
);
521545
}
522546

523547
isEqual(other: Mutation): boolean {

packages/firestore/src/model/mutation_batch.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,7 @@ export class MutationBatchResult {
184184
let versionMap = documentVersionMap();
185185
const mutations = batch.mutations;
186186
for (let i = 0; i < mutations.length; i++) {
187-
let version = results[i].version;
188-
if (version === null) {
189-
// deletes don't have a version, so we substitute the commitVersion
190-
// of the entire batch.
191-
version = commitVersion;
192-
}
193-
194-
versionMap = versionMap.insert(mutations[i].key, version);
187+
versionMap = versionMap.insert(mutations[i].key, results[i].version);
195188
}
196189

197190
return new MutationBatchResult(

packages/firestore/src/remote/datastore.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export class Datastore {
8787
'Commit',
8888
params
8989
).then(response => {
90-
return this.serializer.fromWriteResults(response.writeResults);
90+
return this.serializer.fromWriteResults(
91+
response.writeResults,
92+
response.commitTime
93+
);
9194
});
9295
}
9396

packages/firestore/src/remote/persistent_stream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,8 @@ export class PersistentWriteStream extends PersistentStream<
730730
this.backoff.reset();
731731

732732
const results = this.serializer.fromWriteResults(
733-
responseProto.writeResults
733+
responseProto.writeResults,
734+
responseProto.commitTime
734735
);
735736
const commitVersion = this.serializer.fromVersion(
736737
responseProto.commitTime!

0 commit comments

Comments
 (0)