Skip to content

Commit 1b54073

Browse files
author
Brian Chen
authored
Replace usage of transform with updateTransforms (#4153)
1 parent 6d64028 commit 1b54073

File tree

18 files changed

+569
-380
lines changed

18 files changed

+569
-380
lines changed

.changeset/rich-birds-wink.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
'@firebase/firestore': minor
3+
---
4+
A write to a document that contains FieldValue transforms is no longer split up into two separate operations. This reduces the number of writes the backend performs and allows each WriteBatch to hold 500 writes regardless of how many FieldValue transformations are attached.

packages/firestore/exp/src/api/reference.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,8 @@ export function setDoc<T>(
314314
options
315315
);
316316

317-
const mutations = parsed.toMutations(reference._key, Precondition.none());
318-
return executeWrite(firestore, mutations);
317+
const mutation = parsed.toMutation(reference._key, Precondition.none());
318+
return executeWrite(firestore, [mutation]);
319319
}
320320

321321
/**
@@ -394,11 +394,8 @@ export function updateDoc(
394394
);
395395
}
396396

397-
const mutations = parsed.toMutations(
398-
reference._key,
399-
Precondition.exists(true)
400-
);
401-
return executeWrite(firestore, mutations);
397+
const mutation = parsed.toMutation(reference._key, Precondition.exists(true));
398+
return executeWrite(firestore, [mutation]);
402399
}
403400

404401
/**
@@ -448,8 +445,8 @@ export function addDoc<T>(
448445
{}
449446
);
450447

451-
const mutations = parsed.toMutations(docRef._key, Precondition.exists(false));
452-
return executeWrite(firestore, mutations).then(() => docRef);
448+
const mutation = parsed.toMutation(docRef._key, Precondition.exists(false));
449+
return executeWrite(firestore, [mutation]).then(() => docRef);
453450
}
454451

455452
// TODO(firestorexp): Make sure these overloads are tested via the Firestore

packages/firestore/exp/src/api/snapshot.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,9 @@ export interface DocumentChange<T = DocumentData> {
176176
* access will return 'undefined'. You can use the `exists()` method to
177177
* explicitly verify a document's existence.
178178
*/
179-
export class DocumentSnapshot<
180-
T = DocumentData
181-
> extends LiteDocumentSnapshot<T> {
179+
export class DocumentSnapshot<T = DocumentData> extends LiteDocumentSnapshot<
180+
T
181+
> {
182182
private readonly _firestoreImpl: FirebaseFirestore;
183183

184184
/**
@@ -291,9 +291,9 @@ export class DocumentSnapshot<
291291
* `exists` property will always be true and `data()` will never return
292292
* 'undefined'.
293293
*/
294-
export class QueryDocumentSnapshot<
295-
T = DocumentData
296-
> extends DocumentSnapshot<T> {
294+
export class QueryDocumentSnapshot<T = DocumentData> extends DocumentSnapshot<
295+
T
296+
> {
297297
/**
298298
* Retrieves all fields in the document as an `Object`.
299299
*

packages/firestore/lite/src/api/reference.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,10 +1478,9 @@ export function setDoc<T>(
14781478
);
14791479

14801480
const datastore = getDatastore(reference.firestore);
1481-
return invokeCommitRpc(
1482-
datastore,
1483-
parsed.toMutations(reference._key, Precondition.none())
1484-
);
1481+
return invokeCommitRpc(datastore, [
1482+
parsed.toMutation(reference._key, Precondition.none())
1483+
]);
14851484
}
14861485

14871486
/**
@@ -1569,10 +1568,9 @@ export function updateDoc(
15691568
}
15701569

15711570
const datastore = getDatastore(reference.firestore);
1572-
return invokeCommitRpc(
1573-
datastore,
1574-
parsed.toMutations(reference._key, Precondition.exists(true))
1575-
);
1571+
return invokeCommitRpc(datastore, [
1572+
parsed.toMutation(reference._key, Precondition.exists(true))
1573+
]);
15761574
}
15771575

15781576
/**
@@ -1634,10 +1632,9 @@ export function addDoc<T>(
16341632
);
16351633

16361634
const datastore = getDatastore(reference.firestore);
1637-
return invokeCommitRpc(
1638-
datastore,
1639-
parsed.toMutations(docRef._key, Precondition.exists(false))
1640-
).then(() => docRef);
1635+
return invokeCommitRpc(datastore, [
1636+
parsed.toMutation(docRef._key, Precondition.exists(false))
1637+
]).then(() => docRef);
16411638
}
16421639

16431640
/**

packages/firestore/lite/src/api/snapshot.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ export class DocumentSnapshot<T = DocumentData> {
211211
* `exists` property will always be true and `data()` will never return
212212
* 'undefined'.
213213
*/
214-
export class QueryDocumentSnapshot<
215-
T = DocumentData
216-
> extends DocumentSnapshot<T> {
214+
export class QueryDocumentSnapshot<T = DocumentData> extends DocumentSnapshot<
215+
T
216+
> {
217217
/**
218218
* Retrieves all fields in the document as an `Object`.
219219
*

packages/firestore/lite/src/api/write_batch.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,7 @@ export class WriteBatch {
111111
ref._converter !== null,
112112
options
113113
);
114-
this._mutations = this._mutations.concat(
115-
parsed.toMutations(ref._key, Precondition.none())
116-
);
114+
this._mutations.push(parsed.toMutation(ref._key, Precondition.none()));
117115
return this;
118116
}
119117

@@ -186,8 +184,8 @@ export class WriteBatch {
186184
);
187185
}
188186

189-
this._mutations = this._mutations.concat(
190-
parsed.toMutations(ref._key, Precondition.exists(true))
187+
this._mutations.push(
188+
parsed.toMutation(ref._key, Precondition.exists(true))
191189
);
192190
return this;
193191
}

packages/firestore/src/api/user_data_reader.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717

1818
import {
1919
DocumentData,
20-
SetOptions,
21-
FieldPath as PublicFieldPath
20+
FieldPath as PublicFieldPath,
21+
SetOptions
2222
} from '@firebase/firestore-types';
2323

2424
import {
25-
Value as ProtoValue,
26-
MapValue as ProtoMapValue
25+
MapValue as ProtoMapValue,
26+
Value as ProtoValue
2727
} from '../protos/firestore_proto_api';
2828
import { Timestamp } from './timestamp';
2929
import { DatabaseId } from '../core/database_info';
@@ -34,8 +34,7 @@ import {
3434
Mutation,
3535
PatchMutation,
3636
Precondition,
37-
SetMutation,
38-
TransformMutation
37+
SetMutation
3938
} from '../model/mutation';
4039
import { FieldPath as InternalFieldPath } from '../model/path';
4140
import { debugAssert, fail } from '../util/assert';
@@ -79,38 +78,43 @@ export class ParsedSetData {
7978
readonly fieldTransforms: FieldTransform[]
8079
) {}
8180

82-
toMutations(key: DocumentKey, precondition: Precondition): Mutation[] {
83-
const mutations = [] as Mutation[];
81+
toMutation(key: DocumentKey, precondition: Precondition): Mutation {
8482
if (this.fieldMask !== null) {
85-
mutations.push(
86-
new PatchMutation(key, this.data, this.fieldMask, precondition)
83+
return new PatchMutation(
84+
key,
85+
this.data,
86+
this.fieldMask,
87+
precondition,
88+
this.fieldTransforms
8789
);
8890
} else {
89-
mutations.push(new SetMutation(key, this.data, precondition));
90-
}
91-
if (this.fieldTransforms.length > 0) {
92-
mutations.push(new TransformMutation(key, this.fieldTransforms));
91+
return new SetMutation(
92+
key,
93+
this.data,
94+
precondition,
95+
this.fieldTransforms
96+
);
9397
}
94-
return mutations;
9598
}
9699
}
97100

98101
/** The result of parsing "update" data (i.e. for an updateData call). */
99102
export class ParsedUpdateData {
100103
constructor(
101104
readonly data: ObjectValue,
105+
// The fieldMask does not include document transforms.
102106
readonly fieldMask: FieldMask,
103107
readonly fieldTransforms: FieldTransform[]
104108
) {}
105109

106-
toMutations(key: DocumentKey, precondition: Precondition): Mutation[] {
107-
const mutations = [
108-
new PatchMutation(key, this.data, this.fieldMask, precondition)
109-
] as Mutation[];
110-
if (this.fieldTransforms.length > 0) {
111-
mutations.push(new TransformMutation(key, this.fieldTransforms));
112-
}
113-
return mutations;
110+
toMutation(key: DocumentKey, precondition: Precondition): Mutation {
111+
return new PatchMutation(
112+
key,
113+
this.data,
114+
this.fieldMask,
115+
precondition,
116+
this.fieldTransforms
117+
);
114118
}
115119
}
116120

packages/firestore/src/core/transaction.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,21 @@ export class Transaction {
8181
}
8282

8383
set(key: DocumentKey, data: ParsedSetData): void {
84-
this.write(data.toMutations(key, this.precondition(key)));
84+
this.write(data.toMutation(key, this.precondition(key)));
8585
this.writtenDocs.add(key.toString());
8686
}
8787

8888
update(key: DocumentKey, data: ParsedUpdateData): void {
8989
try {
90-
this.write(data.toMutations(key, this.preconditionForUpdate(key)));
90+
this.write(data.toMutation(key, this.preconditionForUpdate(key)));
9191
} catch (e) {
9292
this.lastWriteError = e;
9393
}
9494
this.writtenDocs.add(key.toString());
9595
}
9696

9797
delete(key: DocumentKey): void {
98-
this.write([new DeleteMutation(key, this.precondition(key))]);
98+
this.write(new DeleteMutation(key, this.precondition(key)));
9999
this.writtenDocs.add(key.toString());
100100
}
101101

@@ -193,9 +193,9 @@ export class Transaction {
193193
}
194194
}
195195

196-
private write(mutations: Mutation[]): void {
196+
private write(mutation: Mutation): void {
197197
this.ensureCommitNotCalled();
198-
this.mutations = this.mutations.concat(mutations);
198+
this.mutations.push(mutation);
199199
}
200200

201201
private ensureCommitNotCalled(): void {

packages/firestore/src/local/local_serializer.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,28 @@ export function fromDbMutationBatch(
194194
const baseMutations = (dbBatch.baseMutations || []).map(m =>
195195
fromMutation(localSerializer.remoteSerializer, m)
196196
);
197+
198+
// Squash old transform mutations into existing patch or set mutations.
199+
// The replacement of representing `transforms` with `update_transforms`
200+
// on the SDK means that old `transform` mutations stored in IndexedDB need
201+
// to be updated to `update_transforms`.
202+
// TODO(b/174608374): Remove this code once we perform a schema migration.
203+
for (let i = dbBatch.mutations.length - 1; i >= 0; --i) {
204+
const mutationProto = dbBatch.mutations[i];
205+
if (mutationProto?.transform !== undefined) {
206+
debugAssert(
207+
i >= 1 &&
208+
dbBatch.mutations[i - 1].transform === undefined &&
209+
dbBatch.mutations[i - 1].update !== undefined,
210+
'TransformMutation should be preceded by a patch or set mutation'
211+
);
212+
const mutationToJoin = dbBatch.mutations[i - 1];
213+
mutationToJoin.updateTransforms = mutationProto.transform.fieldTransforms;
214+
dbBatch.mutations.splice(i, 1);
215+
--i;
216+
}
217+
}
218+
197219
const mutations = dbBatch.mutations.map(m =>
198220
fromMutation(localSerializer.remoteSerializer, m)
199221
);

0 commit comments

Comments
 (0)