Skip to content

Commit

Permalink
Compat class for WriteBatch
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidt-sebastian committed Nov 10, 2020
1 parent f676f67 commit 3fcdff9
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 170 deletions.
2 changes: 2 additions & 0 deletions packages/firestore/exp/src/api/write_batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { FirebaseFirestore } from './database';
import { executeWrite } from './reference';
import { ensureFirestoreConfigured } from '../../../src/api/database';

export { WriteBatch };

/**
* Creates a write batch, used for performing multiple writes as a single
* atomic operation. The maximum number of writes allowed in a single WriteBatch
Expand Down
57 changes: 0 additions & 57 deletions packages/firestore/exp/test/shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,63 +127,6 @@ export class Transaction
}
}

export class WriteBatch
extends Compat<exp.WriteBatch>
implements legacy.WriteBatch {
set<T>(
documentRef: DocumentReference<T>,
data: T,
options?: legacy.SetOptions
): WriteBatch {
if (options) {
validateSetOptions('WriteBatch.set', options);
this._delegate.set(documentRef._delegate, unwrap(data), options);
} else {
this._delegate.set(documentRef._delegate, unwrap(data));
}
return this;
}

update(
documentRef: DocumentReference<any>,
data: legacy.UpdateData
): WriteBatch;
update(
documentRef: DocumentReference<any>,
field: string | FieldPath,
value: any,
...moreFieldsAndValues: any[]
): WriteBatch;
update(
documentRef: DocumentReference<any>,
dataOrField: any,
value?: any,
...moreFieldsAndValues: any[]
): WriteBatch {
if (arguments.length === 2) {
this._delegate.update(documentRef._delegate, unwrap(dataOrField));
} else {
this._delegate.update(
documentRef._delegate,
unwrap(dataOrField),
unwrap(value),
...unwrap(moreFieldsAndValues)
);
}

return this;
}

delete(documentRef: DocumentReference<any>): WriteBatch {
this._delegate.delete(documentRef._delegate);
return this;
}

commit(): Promise<void> {
return this._delegate.commit();
}
}

export class DocumentSnapshot<T = legacy.DocumentData>
extends Compat<exp.DocumentSnapshot<T>>
implements legacy.DocumentSnapshot<T> {
Expand Down
7 changes: 7 additions & 0 deletions packages/firestore/lite/src/api/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import {
import { newSerializer } from '../../../src/platform/serializer';
import { Code, FirestoreError } from '../../../src/util/error';
import { getDatastore } from './components';
import { Compat } from '../../../src/compat/compat';

/**
* Document data (for use with {@link setDoc()}) consists of fields mapped to
Expand Down Expand Up @@ -1086,6 +1087,12 @@ export function updateDoc(
): Promise<void> {
const dataReader = newUserDataReader(reference.firestore);

// For Compat types, we have to "extract" the underlying types before
// performing validation.
if (fieldOrUpdateData instanceof Compat) {
fieldOrUpdateData = fieldOrUpdateData._delegate;
}

let parsed: ParsedUpdateData;
if (
typeof fieldOrUpdateData === 'string' ||
Expand Down
7 changes: 7 additions & 0 deletions packages/firestore/lite/src/api/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
} from './reference';
import { FieldPath } from './field_path';
import { getDatastore } from './components';
import { Compat } from '../../../src/compat/compat';

// TODO(mrschmidt) Consider using `BaseTransaction` as the base class in the
// legacy SDK.
Expand Down Expand Up @@ -194,6 +195,12 @@ export class Transaction {
): this {
const ref = validateReference(documentRef, this._firestore);

// For Compat types, we have to "extract" the underlying types before
// performing validation.
if (fieldOrUpdateData instanceof Compat) {
fieldOrUpdateData = fieldOrUpdateData._delegate;
}

let parsed;
if (
typeof fieldOrUpdateData === 'string' ||
Expand Down
13 changes: 11 additions & 2 deletions packages/firestore/lite/src/api/write_batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { FirebaseFirestore } from './database';
import { invokeCommitRpc } from '../../../src/remote/datastore';
import { FieldPath } from './field_path';
import { getDatastore } from './components';
import { Compat } from '../../../src/compat/compat';

/**
* A write batch, used to perform multiple writes as a single atomic unit.
Expand Down Expand Up @@ -155,8 +156,13 @@ export class WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(documentRef, this._firestore);

let parsed;
// For Compat types, we have to "extract" the underlying types before
// performing validation.
if (fieldOrUpdateData instanceof Compat) {
fieldOrUpdateData = fieldOrUpdateData._delegate;
}

let parsed;
if (
typeof fieldOrUpdateData === 'string' ||
fieldOrUpdateData instanceof FieldPath
Expand Down Expand Up @@ -233,9 +239,12 @@ export class WriteBatch {
}

export function validateReference<T>(
documentRef: DocumentReference<T>,
documentRef: DocumentReference<T> | Compat<DocumentReference<T>>,
firestore: FirebaseFirestore
): DocumentReference<T> {
if (documentRef instanceof Compat) {
documentRef = documentRef._delegate;
}
if (documentRef.firestore !== firestore) {
throw new FirestoreError(
Code.INVALID_ARGUMENT,
Expand Down
148 changes: 37 additions & 111 deletions packages/firestore/src/api/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ import {
firestoreClientGetDocumentsFromLocalCache,
firestoreClientGetDocumentsViaSnapshotListener,
firestoreClientListen,
firestoreClientTransaction,
firestoreClientWrite
firestoreClientTransaction
} from '../core/firestore_client';
import {
Bound,
Expand Down Expand Up @@ -59,7 +58,6 @@ import { Transaction as InternalTransaction } from '../core/transaction';
import { ChangeType, ViewSnapshot } from '../core/view_snapshot';
import { Document, MaybeDocument, NoDocument } from '../model/document';
import { DocumentKey } from '../model/document_key';
import { DeleteMutation, Mutation, Precondition } from '../model/mutation';
import { FieldPath, ResourcePath } from '../model/path';
import { isServerTimestamp } from '../model/server_timestamps';
import { refValue } from '../model/values';
Expand Down Expand Up @@ -118,11 +116,13 @@ import {
getDocFromCache,
getDocFromServer,
getDoc,
onSnapshot
onSnapshot,
executeWrite
} from '../../exp/src/api/reference';
import { DocumentSnapshot as ExpDocumentSnapshot } from '../../exp/src/api/snapshot';
import { LRU_COLLECTION_DISABLED } from '../local/lru_garbage_collector';
import { Compat } from '../compat/compat';
import { WriteBatch as ExpWriteBatch } from '../../exp/src/api/write_batch';

import {
CollectionReference as PublicCollectionReference,
Expand Down Expand Up @@ -154,6 +154,7 @@ import {

import { makeDatabaseInfo } from '../../lite/src/api/database';
import { DEFAULT_HOST } from '../../lite/src/api/components';
import * as exp from '../../exp/index';

/**
* Constant used to indicate the LRU garbage collection should be disabled.
Expand Down Expand Up @@ -399,7 +400,11 @@ export class Firestore

batch(): PublicWriteBatch {
ensureFirestoreConfigured(this._delegate);
return new WriteBatch(this);
return new WriteBatch(
new ExpWriteBatch(this._delegate, mutations =>
executeWrite(this._delegate, mutations)
)
);
}
}

Expand Down Expand Up @@ -590,141 +595,62 @@ export class Transaction implements PublicTransaction {
}
}

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

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

export class WriteBatch
extends Compat<exp.WriteBatch>
implements PublicWriteBatch {
set<T>(
documentRef: DocumentReference<T>,
data: Partial<T>,
options: PublicSetOptions
): WriteBatch;
set<T>(documentRef: DocumentReference<T>, data: T): WriteBatch;
set<T>(
documentRef: PublicDocumentReference<T>,
value: T | Partial<T>,
data: T,
options?: PublicSetOptions
): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(
'WriteBatch.set',
documentRef,
this._firestore
);
options = validateSetOptions('WriteBatch.set', options);
const convertedValue = applyFirestoreDataConverter(
ref._converter,
value,
options
);
const parsed = parseSetData(
this._dataReader,
'WriteBatch.set',
ref._key,
convertedValue,
ref._converter !== null,
options
);
this._mutations = this._mutations.concat(
parsed.toMutations(ref._key, Precondition.none())
);
if (options) {
validateSetOptions('WriteBatch.set', options);
this._delegate.set(documentRef._delegate, data, options);
} else {
this._delegate.set(documentRef._delegate, data);
}
return this;
}

update(
documentRef: PublicDocumentReference<unknown>,
value: PublicUpdateData
documentRef: DocumentReference<unknown>,
data: PublicUpdateData
): WriteBatch;
update(
documentRef: PublicDocumentReference<unknown>,
documentRef: DocumentReference<unknown>,
field: string | PublicFieldPath,
value: unknown,
...moreFieldsAndValues: unknown[]
): WriteBatch;
update(
documentRef: PublicDocumentReference<unknown>,
fieldOrUpdateData: string | PublicFieldPath | PublicUpdateData,
documentRef: DocumentReference<unknown>,
dataOrField: unknown,
value?: unknown,
...moreFieldsAndValues: unknown[]
): WriteBatch {
this.verifyNotCommitted();
const ref = validateReference(
'WriteBatch.update',
documentRef,
this._firestore
);

// For Compat types, we have to "extract" the underlying types before
// performing validation.
if (fieldOrUpdateData instanceof Compat) {
fieldOrUpdateData = (fieldOrUpdateData as Compat<ExpFieldPath>)._delegate;
}

let parsed;
if (
typeof fieldOrUpdateData === 'string' ||
fieldOrUpdateData instanceof ExpFieldPath
) {
parsed = parseUpdateVarargs(
this._dataReader,
'WriteBatch.update',
ref._key,
fieldOrUpdateData,
value,
moreFieldsAndValues
if (arguments.length === 2) {
this._delegate.update(
documentRef._delegate,
dataOrField as PublicUpdateData
);
} else {
parsed = parseUpdateData(
this._dataReader,
'WriteBatch.update',
ref._key,
fieldOrUpdateData
this._delegate.update(
documentRef._delegate,
dataOrField as string | ExpFieldPath,
value,
...moreFieldsAndValues
);
}

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

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

commit(): Promise<void> {
this.verifyNotCommitted();
this._committed = true;
if (this._mutations.length > 0) {
const client = ensureFirestoreConfigured(this._firestore._delegate);
return firestoreClientWrite(client, 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.'
);
}
return this._delegate.commit();
}
}

Expand Down

0 comments on commit 3fcdff9

Please sign in to comment.