Skip to content

Fix a ConcurrentModificationException in ObjectValue overlays #3062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 20, 2021

Conversation

kmsbernard
Copy link
Contributor

I observed ConcurrentModificationException in some race conditions. Following stack trace logged via Crashlystics;

java.util.HashMap$HashIterator.nextNode (HashMap.java:1441)
java.util.HashMap$EntryIterator.next (HashMap.java:1475)
java.util.HashMap$EntryIterator.next (HashMap.java:1473)
com.google.firebase.firestore.model.ObjectValue.applyOverlay (ObjectValue.java:221)
com.google.firebase.firestore.model.ObjectValue.buildProto (ObjectValue.java:127)
com.google.firebase.firestore.model.ObjectValue.getFieldsMap (ObjectValue.java:64)
com.google.firebase.firestore.DocumentSnapshot.getData (DocumentSnapshot.java:148)
com.google.firebase.firestore.DocumentSnapshot.getData (DocumentSnapshot.java:132)

It seems that rapid setting/getting overlays in ObjectValue could result ConcurrentModificationException.

@google-cla
Copy link

google-cla bot commented Oct 18, 2021

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added the cla: no label Oct 18, 2021
@google-oss-bot
Copy link
Contributor

Hi @bernard-kms. Thanks for your PR.

I'm waiting for a firebase member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@kmsbernard
Copy link
Contributor Author

@googlebot I signed it!

@google-cla google-cla bot added cla: yes Override cla and removed cla: no labels Oct 18, 2021
@wu-hui
Copy link
Contributor

wu-hui commented Oct 18, 2021

Hi @bernard-kms

Thank you for the PR! This does look like ObjectValue has a concurrent issue.

What I am worried about is that this should not happen, because on the write path users are not supposed to get hold of a ObjectValue instance that is already associated with a DocumentSnapshot. So while this might fix the issue, there is potentially a bigger issue we need to find.

Do you mind sharing how you are making the writes?

@wu-hui wu-hui self-assigned this Oct 18, 2021
@wu-hui wu-hui self-requested a review October 18, 2021 15:45
@kmsbernard
Copy link
Contributor Author

Hi! Thanks for the quick response.

Actually I also confused with this race happened. Crashlystics logs have the following in common:

  • Occurred in the app widget.
  • Occurred while read data from document snapshot (DocumentSnapshot.getData())

Making writes are somewhat simple:

val documentId = model.getId()
val reference = getCollection(userUid).document(documentId)
reference.set(model.getHashMap()), SetOptions.merge())

And making reads are:

val reference = getCollection(userUid).document(documentId)
return withContext(Dispatchers.IO) {
    val snapshot = reference.get().await()
    if (snapshot.exists()) {
        Model.fromSnapshot(snapshot)
    ...
// Model.kt
data class Model(
    ...
    fun fromSnapshot(doc: DocumentSnapshot): Model {
        val data = doc.data
        if (data != null) {
            return Model(...

All async tasks are handled with kotlin coroutines.

@wu-hui
Copy link
Contributor

wu-hui commented Oct 18, 2021

I am not very sure, but I think the race condition is within ObjectValue.buildProto, btw applyOverlay and overlayMap.clear().

Do you mind trying to lock on this.overlayMap and see if this resolves the issue?

@wu-hui wu-hui assigned kmsbernard and unassigned wu-hui Oct 18, 2021
@kmsbernard
Copy link
Contributor Author

Sure! I will try to repro this issue with a test code and see what happens.

@kmsbernard
Copy link
Contributor Author

kmsbernard commented Oct 19, 2021

I did some more investigations, it seems more likely caused by ObjectValue.set() and ObjectValue.getFieldsMap(). The exact user scenario is still unknown, though.

I tried to reproduce the situation with unit test and the following is the closest repro to got similar stack trace from Crashlystics:

ObjectValue objectValue = new ObjectValue();
int i = 0;
while (i++ < 1000) {
  objectValue.set(field(i + ""), fooValue);
  new Thread(new Runnable() {
    @Override
    public void run() {
      for (Map.Entry<String, Value> entry : objectValue.getFieldsMap().entrySet()) {}
    }
  }).start();
}
Exception in thread "Thread-785" java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
	at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
	at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
	at com.google.firebase.firestore.model.ObjectValue.applyOverlay(ObjectValue.java:221)
	at com.google.firebase.firestore.model.ObjectValue.buildProto(ObjectValue.java:127)
	at com.google.firebase.firestore.model.ObjectValue.getFieldsMap(ObjectValue.java:64)

I also tried lock variable this.overlayMap itself with adding some setter/getter, but it required to refactorsetOverlay().

Please let me know if I missed something.


Edit:

In my thought, synchronized method would be minimal changes to resolve the issue.

@wu-hui
Copy link
Contributor

wu-hui commented Oct 19, 2021

Thanks for the analysis and research!

My main concern is the way you tested it (making get and set concurrently) should not happen. With a DocumentSnapshot its ObjectValue cannot be set again, user code has to read/copy the data out and set it to a DocumentReference, which leads to a complete separate instance of ObjectValue.

ObjectValue.buildProto() however, might be called concurrently (it is used by a bunch of public methods like get*, toString, equals, hashCode, clone...). And I suspect this is where we need to synchronize. Can you try make buildProto sync and see if crashlytics still report concurrency error with you App?

@kmsbernard
Copy link
Contributor Author

Oh now I completely realize what it means and your concern. I will make buildProto synchronized and see how it makes difference in the app.

@kmsbernard
Copy link
Contributor Author

It seems not-too-small ObjectValue overlay actually leads to ConcurrentModificationException within buildProto().

ObjectValue objectValue = new ObjectValue();
int i = 0;
objectValue.set(field("a.b.c"), fooValue);
objectValue.set(field("a.b.d"), fooValue);
objectValue.set(field("f.g"), fooValue);
objectValue.set(field("h"), fooValue);
while (i++ < 1000) {
  new Thread(new Runnable() {
    @Override
    public void run() {
      for (Map.Entry<String, Value> entry : objectValue.getFieldsMap().entrySet()) {}
    }
  }).start();
}

Current PR fix this repro, locking overlayMap in buildProto(). It's running fine in my work app without any report to crashlytics during test.

@wu-hui
Copy link
Contributor

wu-hui commented Oct 20, 2021

/retest

Copy link
Contributor

@wu-hui wu-hui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Thank you very much for this fix, really appreciate it!!

@google-oss-bot
Copy link
Contributor

Coverage Report

Affected SDKs

  • firebase-firestore

    SDK overall coverage changed from ? (69fb475) to 45.13% (dd84bb47) by ?.

    Click to show coverage changes in 296 files.
    Filename Base (69fb475) Head (dd84bb47) Diff
    AbstractStream.java ? 37.02% ?
    ActivityScope.java ? 0.00% ?
    AndroidConnectivityMonitor.java ? 39.51% ?
    ApiUtil.java ? 12.50% ?
    ArrayContainsAnyFilter.java ? 100.00% ?
    ArrayContainsFilter.java ? 100.00% ?
    ArrayTransformOperation.java ? 86.49% ?
    ArrayValue.java ? 48.60% ?
    ArrayValueOrBuilder.java ? 0.00% ?
    Assert.java ? 57.14% ?
    AsyncEventListener.java ? 0.00% ?
    AsyncQueue.java ? 77.11% ?
    AutoValue_FieldIndex_Segment.java ? 34.78% ?
    BackgroundQueue.java ? 100.00% ?
    BasePath.java ? 98.08% ?
    BatchGetDocumentsRequest.java ? 0.00% ?
    BatchGetDocumentsRequestOrBuilder.java ? 0.00% ?
    BatchGetDocumentsResponse.java ? 0.00% ?
    BatchGetDocumentsResponseOrBuilder.java ? 0.00% ?
    BeginTransactionRequest.java ? 0.00% ?
    BeginTransactionRequestOrBuilder.java ? 0.00% ?
    BeginTransactionResponse.java ? 0.00% ?
    BeginTransactionResponseOrBuilder.java ? 0.00% ?
    Blob.java ? 76.92% ?
    Bound.java ? 33.93% ?
    BundleCache.java ? 0.00% ?
    BundleCallback.java ? 0.00% ?
    BundleDocument.java ? 90.00% ?
    BundleElement.java ? 0.00% ?
    BundleElementOrBuilder.java ? 0.00% ?
    BundleLoader.java ? 100.00% ?
    BundleMetadata.java ? 0.00% ?
    BundleMetadataOrBuilder.java ? 0.00% ?
    BundleProto.java ? 0.00% ?
    BundleReader.java ? 95.29% ?
    BundleSerializer.java ? 89.43% ?
    BundledDocumentMetadata.java ? 0.00% ?
    BundledDocumentMetadataOrBuilder.java ? 0.00% ?
    BundledQuery.java ? 34.57% ?
    BundledQueryOrBuilder.java ? 0.00% ?
    ByteBufferInputStream.java ? 83.33% ?
    CollectionReference.java ? 13.64% ?
    CommitRequest.java ? 0.00% ?
    CommitRequestOrBuilder.java ? 0.00% ?
    CommitResponse.java ? 0.00% ?
    CommitResponseOrBuilder.java ? 0.00% ?
    CommonProto.java ? 0.00% ?
    ComponentProvider.java ? 97.30% ?
    ConnectivityMonitor.java ? 0.00% ?
    Consumer.java ? 0.00% ?
    CreateDocumentRequest.java ? 0.00% ?
    CreateDocumentRequestOrBuilder.java ? 0.00% ?
    CredentialsProvider.java ? 100.00% ?
    Cursor.java ? 35.29% ?
    CursorOrBuilder.java ? 0.00% ?
    CustomClassMapper.java ? 84.37% ?
    DatabaseId.java ? 70.37% ?
    DatabaseInfo.java ? 90.91% ?
    Datastore.java ? 32.89% ?
    DatastoreTestTrace.java ? 0.00% ?
    DefaultQueryEngine.java ? 95.65% ?
    DeleteDocumentRequest.java ? 0.00% ?
    DeleteDocumentRequestOrBuilder.java ? 0.00% ?
    DeleteMutation.java ? 95.00% ?
    DirectionalIndexByteEncoder.java ? 100.00% ?
    Document.java ? 100.00% ?
    DocumentChange.java ? 67.61% ?
    DocumentChangeOrBuilder.java ? 0.00% ?
    DocumentCollections.java ? 83.33% ?
    DocumentDelete.java ? 34.62% ?
    DocumentDeleteOrBuilder.java ? 0.00% ?
    DocumentId.java ? 0.00% ?
    DocumentKey.java ? 100.00% ?
    DocumentMask.java ? 40.66% ?
    DocumentMaskOrBuilder.java ? 0.00% ?
    DocumentOrBuilder.java ? 0.00% ?
    DocumentOverlayCache.java ? 0.00% ?
    DocumentProto.java ? 0.00% ?
    DocumentReference.java ? 13.24% ?
    DocumentRemove.java ? 29.23% ?
    DocumentRemoveOrBuilder.java ? 0.00% ?
    DocumentSet.java ? 83.78% ?
    DocumentSnapshot.java ? 37.50% ?
    DocumentTransform.java ? 29.44% ?
    DocumentTransformOrBuilder.java ? 0.00% ?
    DocumentViewChange.java ? 90.91% ?
    DocumentViewChangeSet.java ? 87.88% ?
    EncodedPath.java ? 93.22% ?
    EventListener.java ? 0.00% ?
    EventManager.java ? 96.15% ?
    Exclude.java ? 0.00% ?
    Executors.java ? 100.00% ?
    ExistenceFilter.java ? 80.00% ?
    ExistenceFilterOrBuilder.java ? 0.00% ?
    ExponentialBackoff.java ? 30.43% ?
    FieldFilter.java ? 88.46% ?
    FieldIndex.java ? 76.47% ?
    FieldMask.java ? 55.56% ?
    FieldPath.java ? 89.66% ?
    FieldTransform.java ? 64.71% ?
    FieldValue.java ? 82.14% ?
    FileUtil.java ? 0.00% ?
    Filter.java ? 100.00% ?
    FirebaseAppCheckTokenProvider.java ? 93.75% ?
    FirebaseAuthCredentialsProvider.java ? 100.00% ?
    FirebaseClientGrpcMetadataProvider.java ? 44.00% ?
    FirebaseFirestore.java ? 38.15% ?
    FirebaseFirestoreException.java ? 83.72% ?
    FirebaseFirestoreSettings.java ? 75.00% ?
    FirestoreCallCredentials.java ? 18.60% ?
    FirestoreChannel.java ? 14.91% ?
    FirestoreClient.java ? 30.37% ?
    FirestoreGrpc.java ? 2.62% ?
    FirestoreIndexValueWriter.java ? 77.11% ?
    FirestoreMultiDbComponent.java ? 100.00% ?
    FirestoreProto.java ? 0.00% ?
    FirestoreRegistrar.java ? 100.00% ?
    Function.java ? 0.00% ?
    GeoPoint.java ? 91.67% ?
    GetDocumentRequest.java ? 0.00% ?
    GetDocumentRequestOrBuilder.java ? 0.00% ?
    GrpcCallProvider.java ? 60.23% ?
    GrpcMetadataProvider.java ? 0.00% ?
    IgnoreExtraProperties.java ? 0.00% ?
    InFilter.java ? 100.00% ?
    IncomingStreamObserver.java ? 0.00% ?
    Index.java ? 30.81% ?
    IndexBackfiller.java ? 79.31% ?
    IndexByteEncoder.java ? 88.57% ?
    IndexCursor.java ? 0.00% ?
    IndexEntry.java ? 100.00% ?
    IndexManager.java ? 0.00% ?
    IndexOrBuilder.java ? 0.00% ?
    IndexProto.java ? 0.00% ?
    IndexRange.java ? 88.89% ?
    IndexedQueryEngine.java ? 62.69% ?
    IntMath.java ? 41.67% ?
    KeyFieldFilter.java ? 66.67% ?
    KeyFieldInFilter.java ? 0.00% ?
    KeyFieldNotInFilter.java ? 0.00% ?
    LimboDocumentChange.java ? 70.59% ?
    ListCollectionIdsRequest.java ? 0.00% ?
    ListCollectionIdsRequestOrBuilder.java ? 0.00% ?
    ListCollectionIdsResponse.java ? 0.00% ?
    ListCollectionIdsResponseOrBuilder.java ? 0.00% ?
    ListDocumentsRequest.java ? 0.00% ?
    ListDocumentsRequestOrBuilder.java ? 0.00% ?
    ListDocumentsResponse.java ? 0.00% ?
    ListDocumentsResponseOrBuilder.java ? 0.00% ?
    ListenRequest.java ? 10.77% ?
    ListenRequestOrBuilder.java ? 0.00% ?
    ListenResponse.java ? 32.64% ?
    ListenResponseOrBuilder.java ? 0.00% ?
    ListenSequence.java ? 100.00% ?
    Listener.java ? 0.00% ?
    ListenerRegistration.java ? 0.00% ?
    ListenerRegistrationImpl.java ? 0.00% ?
    LoadBundleTask.java ? 83.16% ?
    LoadBundleTaskProgress.java ? 81.40% ?
    LocalDocumentsView.java ? 100.00% ?
    LocalSerializer.java ? 98.04% ?
    LocalStore.java ? 96.75% ?
    LocalViewChanges.java ? 100.00% ?
    LocalWriteResult.java ? 100.00% ?
    Logger.java ? 75.00% ?
    LruDelegate.java ? 0.00% ?
    LruGarbageCollector.java ? 84.11% ?
    MapValue.java ? 53.00% ?
    MapValueOrBuilder.java ? 0.00% ?
    MemoryBundleCache.java ? 100.00% ?
    MemoryComponentProvider.java ? 100.00% ?
    MemoryDocumentOverlayCache.java ? 100.00% ?
    MemoryEagerReferenceDelegate.java ? 100.00% ?
    MemoryIndexManager.java ? 85.00% ?
    MemoryLruReferenceDelegate.java ? 96.00% ?
    MemoryMutationQueue.java ? 98.58% ?
    MemoryPersistence.java ? 100.00% ?
    MemoryRemoteDocumentCache.java ? 100.00% ?
    MemoryTargetCache.java ? 100.00% ?
    MetadataChanges.java ? 100.00% ?
    MutableDocument.java ? 100.00% ?
    Mutation.java ? 100.00% ?
    MutationBatch.java ? 89.06% ?
    MutationBatchResult.java ? 100.00% ?
    MutationQueue.java ? 0.00% ?
    MutationResult.java ? 100.00% ?
    NamedQuery.java ? 0.00% ?
    NamedQueryOrBuilder.java ? 0.00% ?
    NotInFilter.java ? 85.71% ?
    NumberComparisonHelper.java ? 100.00% ?
    NumericIncrementTransformOperation.java ? 87.50% ?
    ObjectValue.java ? 99.06% ?
    OnProgressListener.java ? 0.00% ?
    OnlineState.java ? 100.00% ?
    OnlineStateTracker.java ? 98.11% ?
    OrderBy.java ? 96.55% ?
    OrderedCodeWriter.java ? 68.52% ?
    PatchMutation.java ? 100.00% ?
    Persistence.java ? 100.00% ?
    Precondition.java ? 38.46% ?
    PreconditionOrBuilder.java ? 0.00% ?
    Preconditions.java ? 68.75% ?
    PropertyName.java ? 0.00% ?
    Query.java ? 4.06% ?
    QueryDocumentSnapshot.java ? 64.71% ?
    QueryEngine.java ? 0.00% ?
    QueryListener.java ? 100.00% ?
    QueryProto.java ? 0.00% ?
    QueryPurpose.java ? 100.00% ?
    QueryResult.java ? 100.00% ?
    QuerySnapshot.java ? 76.36% ?
    QueryView.java ? 100.00% ?
    ReferenceDelegate.java ? 0.00% ?
    ReferenceSet.java ? 92.45% ?
    RemoteDocumentCache.java ? 0.00% ?
    RemoteEvent.java ? 92.31% ?
    RemoteSerializer.java ? 84.63% ?
    RemoteStore.java ? 89.56% ?
    ResourcePath.java ? 94.74% ?
    RollbackRequest.java ? 0.00% ?
    RollbackRequestOrBuilder.java ? 0.00% ?
    RunQueryRequest.java ? 0.00% ?
    RunQueryRequestOrBuilder.java ? 0.00% ?
    RunQueryResponse.java ? 0.00% ?
    RunQueryResponseOrBuilder.java ? 0.00% ?
    SQLiteBundleCache.java ? 90.00% ?
    SQLiteCollectionIndex.java ? 57.14% ?
    SQLiteComponentProvider.java ? 100.00% ?
    SQLiteDocumentOverlayCache.java ? 91.11% ?
    SQLiteIndexManager.java ? 97.56% ?
    SQLiteLruReferenceDelegate.java ? 98.63% ?
    SQLiteMutationQueue.java ? 82.66% ?
    SQLitePersistence.java ? 84.95% ?
    SQLiteRemoteDocumentCache.java ? 95.29% ?
    SQLiteSchema.java ? 96.19% ?
    SQLiteTargetCache.java ? 98.47% ?
    Scheduler.java ? 0.00% ?
    ServerTimestamp.java ? 0.00% ?
    ServerTimestampOperation.java ? 100.00% ?
    ServerTimestamps.java ? 79.17% ?
    SetMutation.java ? 94.29% ?
    SetOptions.java ? 0.00% ?
    SnapshotMetadata.java ? 68.75% ?
    SnapshotVersion.java ? 87.50% ?
    Source.java ? 0.00% ?
    Stream.java ? 100.00% ?
    StructuredQuery.java ? 32.44% ?
    StructuredQueryOrBuilder.java ? 0.00% ?
    Supplier.java ? 0.00% ?
    SyncEngine.java ? 93.57% ?
    Target.java ? 96.12% ?
    TargetCache.java ? 0.00% ?
    TargetChange.java ? 80.00% ?
    TargetChangeOrBuilder.java ? 0.00% ?
    TargetData.java ? 77.50% ?
    TargetIdGenerator.java ? 100.00% ?
    TargetIndexMatcher.java ? 100.00% ?
    TargetOrBuilder.java ? 0.00% ?
    TargetState.java ? 97.78% ?
    ThrottledForwardingExecutor.java ? 100.00% ?
    ThrowOnExtraProperties.java ? 0.00% ?
    Timestamp.java ? 80.39% ?
    Token.java ? 0.00% ?
    Transaction.java ? 0.00% ?
    TransactionOptions.java ? 0.00% ?
    TransactionOptionsOrBuilder.java ? 0.00% ?
    TransactionRunner.java ? 0.00% ?
    TransformOperation.java ? 0.00% ?
    UpdateDocumentRequest.java ? 0.00% ?
    UpdateDocumentRequestOrBuilder.java ? 0.00% ?
    User.java ? 78.57% ?
    UserData.java ? 66.00% ?
    UserDataReader.java ? 70.48% ?
    UserDataWriter.java ? 51.02% ?
    Util.java ? 53.57% ?
    Value.java ? 42.48% ?
    ValueOrBuilder.java ? 0.00% ?
    Values.java ? 95.58% ?
    VerifyMutation.java ? 50.00% ?
    View.java ? 96.82% ?
    ViewChange.java ? 100.00% ?
    ViewSnapshot.java ? 88.33% ?
    WatchChange.java ? 70.51% ?
    WatchChangeAggregator.java ? 98.18% ?
    WatchStream.java ? 19.23% ?
    Write.java ? 36.56% ?
    WriteBatch.java ? 0.00% ?
    WriteOrBuilder.java ? 0.00% ?
    WriteProto.java ? 0.00% ?
    WriteRequest.java ? 10.41% ?
    WriteRequestOrBuilder.java ? 0.00% ?
    WriteResponse.java ? 11.70% ?
    WriteResponseOrBuilder.java ? 0.00% ?
    WriteResult.java ? 0.00% ?
    WriteResultOrBuilder.java ? 0.00% ?
    WriteStream.java ? 31.82% ?

Test Logs

Notes

HTML coverage reports can be produced locally with ./gradlew <product>:checkCoverage.
Report files are located at <product-build-dir>/reports/jacoco/.

Head commit (dd84bb47) is created by Prow via merging commits: 69fb475 ce792be.

@google-oss-bot
Copy link
Contributor

Binary Size Report

Affected SDKs

  • base

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 8.39 kB ? (?)
    apk (release) ? 8.65 kB ? (?)
  • firebase-annotations

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 8.39 kB ? (?)
    apk (release) ? 8.83 kB ? (?)
  • firebase-appcheck-interop

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 281 kB ? (?)
    apk (release) ? 925 kB ? (?)
  • firebase-common

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 77.8 kB ? (?)
    apk (release) ? 635 kB ? (?)
  • firebase-components

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 8.68 kB ? (?)
    apk (release) ? 29.5 kB ? (?)
  • firebase-database-collection

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 268 kB ? (?)
    apk (release) ? 901 kB ? (?)
  • firebase-firestore

    Type Base (69fb475) Head (dd84bb47) Diff
    aar 1.22 MB 1.22 MB +59 B (+0.0%)
    apk (aggressive) ? 443 kB ? (?)
    apk (release) ? 3.32 MB ? (?)
  • protolite-well-known-types

    Type Base (69fb475) Head (dd84bb47) Diff
    apk (aggressive) ? 134 kB ? (?)
    apk (release) ? 661 kB ? (?)

Test Logs

Notes

Head commit (dd84bb47) is created by Prow via merging commits: 69fb475 ce792be.

@google-oss-bot
Copy link
Contributor

@bernard-kms: The following test failed, say /retest to rerun them all:

Test name Commit Details Rerun command
device-check-changed ce792be link /test device-check-changed

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@wu-hui wu-hui merged commit 1d493df into firebase:master Oct 20, 2021
@firebase firebase locked and limited conversation to collaborators Nov 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants