Skip to content

Commit e7054df

Browse files
author
Brian Chen
authored
feat: add BulkWriter (#323)
New BulkWriter leveraging [`BatchWriteRequest`](https://github.com/googleapis/googleapis/blob/393d03088e368d79c8f4cd5e3610c7df0bb118bf/google/firestore/v1/firestore.proto#L866-L881) which allows for fine grain batch processing of documents. Where as existing `WriteBatch` is an atomic write (all succeed or all fail). BulkWriter has been implemented to follow the 500/50/5 rule from [Firestore Best Practices: Ramping up traffic](https://firebase.google.com/docs/firestore/best-practices#ramping_up_traffic). If your application is already managing compliance with the 500/50/5 rule, you can configure the `BulkWriter` by using the `Firestore#bulkWriter(com.google.cloud.firestore.BulkWriterOptions)` method.
1 parent 269e62c commit e7054df

20 files changed

+2254
-77
lines changed

google-cloud-firestore/clirr-ignored-differences.xml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,44 @@
161161
<method>com.google.cloud.firestore.Query collectionGroup(java.lang.String)</method>
162162
<to>com.google.cloud.firestore.CollectionGroup</to>
163163
</difference>
164+
165+
<!--
166+
BulkWriter
167+
-->
168+
<difference>
169+
<differenceType>7012</differenceType>
170+
<className>com/google/cloud/firestore/Firestore</className>
171+
<method>com.google.cloud.firestore.BulkWriter bulkWriter(*)</method>
172+
</difference>
173+
<difference>
174+
<differenceType>7006</differenceType>
175+
<className>com/google/cloud/firestore/UpdateBuilder</className>
176+
<method>com.google.cloud.firestore.UpdateBuilder create(*)</method>
177+
<to>java.lang.Object</to>
178+
</difference>
179+
<difference>
180+
<differenceType>7006</differenceType>
181+
<className>com/google/cloud/firestore/UpdateBuilder</className>
182+
<method>com.google.cloud.firestore.UpdateBuilder delete(*)</method>
183+
<to>java.lang.Object</to>
184+
</difference>
185+
<difference>
186+
<differenceType>7006</differenceType>
187+
<className>com/google/cloud/firestore/UpdateBuilder</className>
188+
<method>com.google.cloud.firestore.UpdateBuilder set(*)</method>
189+
<to>java.lang.Object</to>
190+
</difference>
191+
<difference>
192+
<differenceType>7006</differenceType>
193+
<className>com/google/cloud/firestore/UpdateBuilder</className>
194+
<method>com.google.cloud.firestore.UpdateBuilder update(*)</method>
195+
<to>java.lang.Object</to>
196+
</difference>
197+
<difference>
198+
<differenceType>7012</differenceType>
199+
<className>com/google/cloud/firestore/spi/v1/FirestoreRpc</className>
200+
<method>com.google.api.gax.rpc.UnaryCallable batchWriteCallable()</method>
201+
</difference>
164202

165203
<!--
166204
FakeCredentials Refactor
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore;
18+
19+
import com.google.api.core.InternalApi;
20+
import com.google.cloud.Timestamp;
21+
import javax.annotation.Nullable;
22+
23+
/**
24+
* A BatchWriteResult wraps the write time and status returned by Firestore when making
25+
* BatchWriteRequests.
26+
*/
27+
@InternalApi
28+
public final class BatchWriteResult {
29+
private final DocumentReference documentReference;
30+
@Nullable private final Timestamp writeTime;
31+
@Nullable private final Exception exception;
32+
33+
BatchWriteResult(
34+
DocumentReference documentReference,
35+
@Nullable Timestamp timestamp,
36+
@Nullable Exception exception) {
37+
this.documentReference = documentReference;
38+
this.writeTime = timestamp;
39+
this.exception = exception;
40+
}
41+
42+
public DocumentReference getDocumentReference() {
43+
return documentReference;
44+
}
45+
46+
@Nullable
47+
public Timestamp getWriteTime() {
48+
return writeTime;
49+
}
50+
51+
@Nullable
52+
public Exception getException() {
53+
return exception;
54+
}
55+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore;
18+
19+
import com.google.api.core.ApiFuture;
20+
import com.google.common.base.Preconditions;
21+
import com.google.common.base.Predicate;
22+
import com.google.common.collect.FluentIterable;
23+
import java.util.Set;
24+
25+
/** Used to represent a batch on the BatchQueue. */
26+
class BulkCommitBatch extends UpdateBuilder<ApiFuture<WriteResult>> {
27+
28+
BulkCommitBatch(FirestoreImpl firestore, int maxBatchSize) {
29+
super(firestore, maxBatchSize);
30+
}
31+
32+
BulkCommitBatch(
33+
FirestoreImpl firestore,
34+
BulkCommitBatch retryBatch,
35+
final Set<DocumentReference> docsToRetry) {
36+
super(firestore);
37+
this.writes.addAll(
38+
FluentIterable.from(retryBatch.writes)
39+
.filter(
40+
new Predicate<WriteOperation>() {
41+
@Override
42+
public boolean apply(WriteOperation writeOperation) {
43+
return docsToRetry.contains(writeOperation.documentReference);
44+
}
45+
})
46+
.toList());
47+
48+
Preconditions.checkState(
49+
retryBatch.state == BatchState.SENT,
50+
"Batch should be SENT when creating a new BulkCommitBatch for retry");
51+
this.state = retryBatch.state;
52+
this.pendingOperations = retryBatch.pendingOperations;
53+
}
54+
55+
ApiFuture<WriteResult> wrapResult(ApiFuture<WriteResult> result) {
56+
return result;
57+
}
58+
59+
@Override
60+
boolean allowDuplicateDocs() {
61+
return false;
62+
}
63+
}

0 commit comments

Comments
 (0)