Skip to content

Commit

Permalink
Merge 5315226 into 982acf9
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidt-sebastian authored Jun 30, 2020
2 parents 982acf9 + 5315226 commit e98cb0f
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 355 deletions.
2 changes: 2 additions & 0 deletions .changeset/serious-tables-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
12 changes: 8 additions & 4 deletions packages/firestore/exp/src/api/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import * as firestore from '../../index';
import { Firestore } from './database';
import {
DocumentKeyReference,
ParsedUpdateData
ParsedUpdateData,
convertSetToMutations,
convertUpdateToMutations
} from '../../../src/api/user_data_reader';
import { debugAssert } from '../../../src/util/assert';
import { cast } from '../../../lite/src/api/util';
Expand Down Expand Up @@ -186,7 +188,9 @@ export function setDoc<T>(
return firestore
._getFirestoreClient()
.then(firestoreClient =>
firestoreClient.write(parsed.toMutations(ref._key, Precondition.none()))
firestoreClient.write(
convertSetToMutations(parsed, ref._key, Precondition.none())
)
);
}

Expand Down Expand Up @@ -234,7 +238,7 @@ export function updateDoc(
._getFirestoreClient()
.then(firestoreClient =>
firestoreClient.write(
parsed.toMutations(ref._key, Precondition.exists(true))
convertUpdateToMutations(parsed, ref._key, Precondition.exists(true))
)
);
}
Expand Down Expand Up @@ -273,7 +277,7 @@ export function addDoc<T>(
._getFirestoreClient()
.then(firestoreClient =>
firestoreClient.write(
parsed.toMutations(docRef._key, Precondition.exists(false))
convertSetToMutations(parsed, docRef._key, Precondition.exists(false))
)
)
.then(() => docRef);
Expand Down
141 changes: 135 additions & 6 deletions packages/firestore/exp/src/api/write_batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,145 @@
import * as firestore from '../../index';

import { cast } from '../../../lite/src/api/util';
import { WriteBatch } from '../../../lite/src/api/write_batch';
import { Firestore } from './database';
import {
DeleteMutation,
Mutation,
Precondition
} from '../../../src/model/mutation';
import { Code, FirestoreError } from '../../../src/util/error';
import { applyFirestoreDataConverter } from '../../../src/api/database';
import {
convertSetToMutations,
convertUpdateToMutations,
UserDataReader
} from '../../../src/api/user_data_reader';
import { newUserDataReader } from '../../../lite/src/api/reference';
import { FieldPath } from '../../../lite/src/api/field_path';
import { validateReference } from '../../../lite/src/api/write_batch';

export class WriteBatch implements firestore.WriteBatch {
private readonly _dataReader: UserDataReader;
private _mutations = [] as Mutation[];
private _committed = false;

constructor(private readonly _firestore: Firestore) {
this._dataReader = newUserDataReader(_firestore);
}

set<T>(documentRef: firestore.DocumentReference<T>, value: T): WriteBatch;
set<T>(
documentRef: firestore.DocumentReference<T>,
value: Partial<T>,
options: firestore.SetOptions
): WriteBatch;
set<T>(
documentRef: firestore.DocumentReference<T>,
value: T,
options?: firestore.SetOptions
): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(documentRef, this._firestore);

const convertedValue = applyFirestoreDataConverter(
ref._converter,
value,
options
);
const parsed = this._dataReader.parseSetData(
'WriteBatch.set',
ref._key,
convertedValue,
ref._converter !== null,
options
);
this._mutations = this._mutations.concat(
convertSetToMutations(parsed, ref._key, Precondition.none())
);
return this;
}

update(
documentRef: firestore.DocumentReference<unknown>,
value: firestore.UpdateData
): WriteBatch;
update(
documentRef: firestore.DocumentReference<unknown>,
field: string | firestore.FieldPath,
value: unknown,
...moreFieldsAndValues: unknown[]
): WriteBatch;
update(
documentRef: firestore.DocumentReference<unknown>,
fieldOrUpdateData: string | firestore.FieldPath | firestore.UpdateData,
value?: unknown,
...moreFieldsAndValues: unknown[]
): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(documentRef, this._firestore);

let parsed;

if (
typeof fieldOrUpdateData === 'string' ||
fieldOrUpdateData instanceof FieldPath
) {
parsed = this._dataReader.parseUpdateVarargs(
'WriteBatch.update',
ref._key,
fieldOrUpdateData,
value,
moreFieldsAndValues
);
} else {
parsed = this._dataReader.parseUpdateData(
'WriteBatch.update',
ref._key,
fieldOrUpdateData
);
}

this._mutations = this._mutations.concat(
convertUpdateToMutations(parsed, ref._key, Precondition.exists(true))
);
return this;
}

delete(documentRef: firestore.DocumentReference<unknown>): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(documentRef, this._firestore);
this._mutations = this._mutations.concat(
new DeleteMutation(ref._key, Precondition.none())
);
return this;
}

commit(): Promise<void> {
this.verifyNotCommitted();
this._committed = true;
if (this._mutations.length > 0) {
return this._firestore
._getFirestoreClient()
.then(firestoreClient => firestoreClient.write(this._mutations));
}

return Promise.resolve();
}

private verifyNotCommitted(): void {
if (this._committed) {
throw new FirestoreError(
Code.FAILED_PRECONDITION,
'A write batch can no longer be used after commit() ' +
'has been called.'
);
}
}
}

export function writeBatch(
firestore: firestore.FirebaseFirestore
): firestore.WriteBatch {
const firestoreImpl = cast(firestore, Firestore);
return new WriteBatch(firestoreImpl, writes =>
firestoreImpl
._getFirestoreClient()
.then(firestoreClient => firestoreClient.write(writes))
);
return new WriteBatch(firestoreImpl);
}
38 changes: 30 additions & 8 deletions packages/firestore/lite/src/api/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import { Firestore } from './database';
import {
DocumentKeyReference,
ParsedUpdateData,
UserDataReader
convertSetToWrites,
convertUpdateToWrites,
UserDataReader,
convertDeleteToWrite
} from '../../../src/api/user_data_reader';
import {
Bound,
Expand All @@ -35,17 +38,17 @@ import { ResourcePath } from '../../../src/model/path';
import { AutoId } from '../../../src/util/misc';
import {
DocumentSnapshot,
fieldPathFromArgument,
QueryDocumentSnapshot,
QuerySnapshot,
fieldPathFromArgument
QuerySnapshot
} from './snapshot';
import {
invokeBatchGetDocumentsRpc,
invokeCommitRpc,
invokeRunQueryRpc
} from '../../../src/remote/datastore';
import { hardAssert } from '../../../src/util/assert';
import { DeleteMutation, Precondition } from '../../../src/model/mutation';
import { Precondition } from '../../../src/model/mutation';
import {
applyFirestoreDataConverter,
BaseQuery,
Expand Down Expand Up @@ -477,7 +480,12 @@ export function setDoc<T>(
.then(datastore =>
invokeCommitRpc(
datastore,
parsed.toMutations(ref._key, Precondition.none())
convertSetToWrites(
parsed,
datastore.serializer,
ref._key,
Precondition.none()
)
)
);
}
Expand Down Expand Up @@ -526,7 +534,12 @@ export function updateDoc(
.then(datastore =>
invokeCommitRpc(
datastore,
parsed.toMutations(ref._key, Precondition.exists(true))
convertUpdateToWrites(
parsed,
datastore.serializer,
ref._key,
Precondition.exists(true)
)
)
);
}
Expand All @@ -539,7 +552,11 @@ export function deleteDoc(
._getDatastore()
.then(datastore =>
invokeCommitRpc(datastore, [
new DeleteMutation(ref._key, Precondition.none())
convertDeleteToWrite(
datastore.serializer,
ref._key,
Precondition.none()
)
])
);
}
Expand Down Expand Up @@ -567,7 +584,12 @@ export function addDoc<T>(
.then(datastore =>
invokeCommitRpc(
datastore,
parsed.toMutations(docRef._key, Precondition.exists(false))
convertSetToWrites(
parsed,
datastore.serializer,
docRef._key,
Precondition.exists(false)
)
)
)
.then(() => docRef);
Expand Down
55 changes: 32 additions & 23 deletions packages/firestore/lite/src/api/write_batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as api from '../../../src/protos/firestore_proto_api';

import * as firestore from '../../index';
import {
DeleteMutation,
Mutation,
Precondition
} from '../../../src/model/mutation';
import { Precondition } from '../../../src/model/mutation';
import { Code, FirestoreError } from '../../../src/util/error';
import { applyFirestoreDataConverter } from '../../../src/api/database';
import {
DocumentKeyReference,
convertDeleteToWrite,
convertSetToWrites,
convertUpdateToWrites,
UserDataReader
} from '../../../src/api/user_data_reader';
import { cast } from './util';
import { DocumentReference, newUserDataReader } from './reference';
import { Firestore } from './database';
import { invokeCommitRpc } from '../../../src/remote/datastore';
import { FieldPath } from './field_path';
import { JsonProtoSerializer } from '../../../src/remote/serializer';
import { newSerializer } from '../../../src/platform/serializer';

export class WriteBatch implements firestore.WriteBatch {
// This is the lite version of the WriteBatch API used in the legacy SDK. The
// class is a close copy but takes different input types.

private readonly _dataReader: UserDataReader;
private _mutations = [] as Mutation[];
private readonly _serializer: JsonProtoSerializer;
private _writes = [] as api.Write[];
private _committed = false;

constructor(
private readonly _firestore: Firestore,
private readonly _commitHandler: (m: Mutation[]) => Promise<void>
) {
constructor(private readonly _firestore: Firestore) {
this._dataReader = newUserDataReader(_firestore);
this._serializer = newSerializer(_firestore._databaseId);
}

set<T>(documentRef: firestore.DocumentReference<T>, value: T): WriteBatch;
Expand Down Expand Up @@ -74,8 +75,13 @@ export class WriteBatch implements firestore.WriteBatch {
ref._converter !== null,
options
);
this._mutations = this._mutations.concat(
parsed.toMutations(ref._key, Precondition.none())
this._writes = this._writes.concat(
convertSetToWrites(
parsed,
this._serializer,
ref._key,
Precondition.none()
)
);
return this;
}
Expand Down Expand Up @@ -120,26 +126,33 @@ export class WriteBatch implements firestore.WriteBatch {
);
}

this._mutations = this._mutations.concat(
parsed.toMutations(ref._key, Precondition.exists(true))
this._writes = this._writes.concat(
convertUpdateToWrites(
parsed,
this._serializer,
ref._key,
Precondition.exists(true)
)
);
return this;
}

delete(documentRef: firestore.DocumentReference<unknown>): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(documentRef, this._firestore);
this._mutations = this._mutations.concat(
new DeleteMutation(ref._key, Precondition.none())
this._writes = this._writes.concat(
convertDeleteToWrite(this._serializer, ref._key, Precondition.none())
);
return this;
}

commit(): Promise<void> {
this.verifyNotCommitted();
this._committed = true;
if (this._mutations.length > 0) {
return this._commitHandler(this._mutations);
if (this._writes.length > 0) {
return this._firestore
._getDatastore()
.then(datastore => invokeCommitRpc(datastore, this._writes));
}

return Promise.resolve();
Expand Down Expand Up @@ -174,9 +187,5 @@ export function writeBatch(
firestore: firestore.FirebaseFirestore
): firestore.WriteBatch {
const firestoreImpl = cast(firestore, Firestore);
return new WriteBatch(firestoreImpl, writes =>
firestoreImpl
._getDatastore()
.then(datastore => invokeCommitRpc(datastore, writes))
);
return new WriteBatch(firestoreImpl);
}
Loading

0 comments on commit e98cb0f

Please sign in to comment.