[go: nahoru, domu]

Skip to content
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

Fix Firestore failing to return empty results from the local cache #4207

Next Next commit
add hasCachedResults flag
  • Loading branch information
milaGGL committed Oct 15, 2022
commit 705bf4fd5880ff42278d74ca87a6580498975628
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public boolean onViewSnapshot(ViewSnapshot newSnapshot) {
newSnapshot.isFromCache(),
newSnapshot.getMutatedKeys(),
newSnapshot.didSyncStateChange(),
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
newSnapshot.hasCachedResults());
}

if (!raisedInitialEvent) {
Expand Down Expand Up @@ -139,8 +140,11 @@ private boolean shouldRaiseInitialEvent(ViewSnapshot snapshot, OnlineState onlin
return false;
}

// Raise data from cache if we have any documents or we are offline
return !snapshot.getDocuments().isEmpty() || onlineState.equals(OnlineState.OFFLINE);
// Raise data from cache if we have any documents, have cached results before,
// or we are offline.
return (!snapshot.getDocuments().isEmpty()
|| snapshot.hasCachedResults()
|| onlineState.equals(OnlineState.OFFLINE));
}

private boolean shouldRaiseEvent(ViewSnapshot snapshot) {
Expand Down Expand Up @@ -171,7 +175,8 @@ private void raiseInitialEvent(ViewSnapshot snapshot) {
snapshot.getDocuments(),
snapshot.getMutatedKeys(),
snapshot.isFromCache(),
snapshot.excludesMetadataChanges());
snapshot.excludesMetadataChanges(),
snapshot.hasCachedResults());
raisedInitialEvent = true;
listener.onEvent(snapshot, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.google.firebase.firestore.util.Function;
import com.google.firebase.firestore.util.Logger;
import com.google.firebase.firestore.util.Util;
import com.google.protobuf.ByteString;
import io.grpc.Status;
import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -204,13 +205,16 @@ public int listen(Query query) {
TargetData targetData = localStore.allocateTarget(query.toTarget());
remoteStore.listen(targetData);

ViewSnapshot viewSnapshot = initializeViewAndComputeSnapshot(query, targetData.getTargetId());
ViewSnapshot viewSnapshot =
initializeViewAndComputeSnapshot(
query, targetData.getTargetId(), targetData.getResumeToken());
syncEngineListener.onViewSnapshots(Collections.singletonList(viewSnapshot));

return targetData.getTargetId();
}

private ViewSnapshot initializeViewAndComputeSnapshot(Query query, int targetId) {
private ViewSnapshot initializeViewAndComputeSnapshot(
Query query, int targetId, ByteString resumeToken) {
QueryResult queryResult = localStore.executeQuery(query, /* usePreviousResults= */ true);

SyncState currentTargetSyncState = SyncState.NONE;
Expand All @@ -223,7 +227,7 @@ private ViewSnapshot initializeViewAndComputeSnapshot(Query query, int targetId)
currentTargetSyncState = this.queryViewsByQuery.get(mirrorQuery).getView().getSyncState();
synthesizedCurrentChange =
TargetChange.createSynthesizedTargetChangeForCurrentChange(
currentTargetSyncState == SyncState.SYNCED);
currentTargetSyncState == SyncState.SYNCED, resumeToken);
}

// TODO(wuandy): Investigate if we can extract the logic of view change computation and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,10 @@ public ViewChange applyChanges(DocumentChanges docChanges, TargetChange targetCh
fromCache,
docChanges.mutatedKeys,
syncStatedChanged,
/* excludesMetadataChanges= */ false);
/* excludesMetadataChanges= */ false,
/* hasCachedResults= */ targetChange == null
dconeybe marked this conversation as resolved.
Show resolved Hide resolved
? false
: !targetChange.getResumeToken().isEmpty());
}
return new ViewChange(snapshot, limboDocumentChanges);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public enum SyncState {
private final ImmutableSortedSet<DocumentKey> mutatedKeys;
private final boolean didSyncStateChange;
private boolean excludesMetadataChanges;
private boolean hasCachedResults;

public ViewSnapshot(
Query query,
Expand All @@ -48,7 +49,8 @@ public ViewSnapshot(
boolean isFromCache,
ImmutableSortedSet<DocumentKey> mutatedKeys,
boolean didSyncStateChange,
boolean excludesMetadataChanges) {
boolean excludesMetadataChanges,
boolean hasCachedResults) {
this.query = query;
this.documents = documents;
this.oldDocuments = oldDocuments;
Expand All @@ -57,6 +59,7 @@ public ViewSnapshot(
this.mutatedKeys = mutatedKeys;
this.didSyncStateChange = didSyncStateChange;
this.excludesMetadataChanges = excludesMetadataChanges;
this.hasCachedResults = hasCachedResults;
}

/** Returns a view snapshot as if all documents in the snapshot were added. */
Expand All @@ -65,7 +68,8 @@ public static ViewSnapshot fromInitialDocuments(
DocumentSet documents,
ImmutableSortedSet<DocumentKey> mutatedKeys,
boolean fromCache,
boolean excludesMetadataChanges) {
boolean excludesMetadataChanges,
boolean hasCachedResults) {
List<DocumentViewChange> viewChanges = new ArrayList<>();
for (Document doc : documents) {
viewChanges.add(DocumentViewChange.create(DocumentViewChange.Type.ADDED, doc));
Expand All @@ -78,7 +82,8 @@ public static ViewSnapshot fromInitialDocuments(
fromCache,
mutatedKeys,
/* didSyncStateChange= */ true,
excludesMetadataChanges);
excludesMetadataChanges,
hasCachedResults);
}

public Query getQuery() {
Expand Down Expand Up @@ -117,6 +122,10 @@ public boolean excludesMetadataChanges() {
return excludesMetadataChanges;
}

public boolean hasCachedResults() {
return hasCachedResults;
}

@Override
public final boolean equals(Object o) {
if (this == o) {
Expand Down Expand Up @@ -149,6 +158,9 @@ public final boolean equals(Object o) {
if (!oldDocuments.equals(that.oldDocuments)) {
return false;
}
if (hasCachedResults != that.hasCachedResults) {
return false;
}
return changes.equals(that.changes);
}

Expand Down Expand Up @@ -183,6 +195,8 @@ public String toString() {
+ didSyncStateChange
+ ", excludesMetadataChanges="
+ excludesMetadataChanges
+ ", hasCachedResults="
+ hasCachedResults
+ ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ public final class TargetChange {
private final ImmutableSortedSet<DocumentKey> modifiedDocuments;
private final ImmutableSortedSet<DocumentKey> removedDocuments;

public static TargetChange createSynthesizedTargetChangeForCurrentChange(boolean isCurrent) {
public static TargetChange createSynthesizedTargetChangeForCurrentChange(
boolean isCurrent, ByteString resumeToken) {
return new TargetChange(
ByteString.EMPTY,
resumeToken,
isCurrent,
DocumentKey.emptyKeySet(),
DocumentKey.emptyKeySet(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public static QuerySnapshot querySnapshot(
isFromCache,
mutatedKeys,
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ false);
/* excludesMetadataChanges= */ false,
/* hasCachedResults= */ false);
return new QuerySnapshot(query(path), viewSnapshot, FIRESTORE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ public void testIncludeMetadataChanges() {
/*isFromCache=*/ false,
/*mutatedKeys=*/ keySet(),
/*didSyncStateChange=*/ true,
/* excludesMetadataChanges= */ false);
/* excludesMetadataChanges= */ false,
/* hasCachedResults= */ false);

QuerySnapshot snapshot =
new QuerySnapshot(new Query(fooQuery, firestore), viewSnapshot, firestore);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ public void testRaisesCollectionEvents() {
snap2.isFromCache(),
snap2.getMutatedKeys(),
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ false);
/* excludesMetadataChanges= */ false,
/* hasCachedResults= */ false);
assertEquals(asList(snap2Prime), otherAccum);
}

Expand Down Expand Up @@ -262,7 +263,8 @@ public void testRaisesQueryMetadataEventsOnlyWhenHasPendingWritesOnTheQueryChang
snap4.isFromCache(),
snap4.getMutatedKeys(),
snap4.didSyncStateChange(),
/* excludeMetadataChanges= */ true); // This test excludes document metadata changes
/* excludeMetadataChanges= */ true,
/* hasCachedResults= */ false); // This test excludes document metadata changes

assertEquals(
asList(
Expand Down Expand Up @@ -302,7 +304,9 @@ public void testMetadataOnlyDocumentChangesAreFilteredOut() {
snap2.isFromCache(),
snap2.getMutatedKeys(),
snap2.didSyncStateChange(),
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);

assertEquals(
asList(applyExpectedMetadata(snap1, MetadataChanges.EXCLUDE), expectedSnapshot2),
filteredAccum);
Expand Down Expand Up @@ -344,7 +348,8 @@ public void testWillWaitForSyncIfOnline() {
/* isFromCache= */ false,
snap3.getMutatedKeys(),
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);
assertEquals(asList(expectedSnapshot), events);
}

Expand Down Expand Up @@ -382,7 +387,9 @@ public void testWillRaiseInitialEventWhenGoingOffline() {
/* isFromCache= */ true,
snap1.getMutatedKeys(),
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);

ViewSnapshot expectedSnapshot2 =
new ViewSnapshot(
snap2.getQuery(),
Expand All @@ -392,7 +399,8 @@ public void testWillRaiseInitialEventWhenGoingOffline() {
/* isFromCache= */ true,
snap2.getMutatedKeys(),
/* didSyncStateChange= */ false,
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);
assertEquals(asList(expectedSnapshot1, expectedSnapshot2), events);
}

Expand All @@ -419,7 +427,8 @@ public void testWillRaiseInitialEventWhenGoingOfflineAndThereAreNoDocs() {
/* isFromCache= */ true,
snap1.getMutatedKeys(),
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);
assertEquals(asList(expectedSnapshot), events);
}

Expand All @@ -445,7 +454,8 @@ public void testWillRaiseInitialEventWhenStartingOfflineAndThereAreNoDocs() {
/* isFromCache= */ true,
snap1.getMutatedKeys(),
/* didSyncStateChange= */ true,
/* excludesMetadataChanges= */ true);
/* excludesMetadataChanges= */ true,
/* hasCachedResults= */ false);
assertEquals(asList(expectedSnapshot), events);
}

Expand All @@ -458,6 +468,7 @@ private ViewSnapshot applyExpectedMetadata(ViewSnapshot snap, MetadataChanges me
snap.isFromCache(),
snap.getMutatedKeys(),
snap.didSyncStateChange(),
MetadataChanges.EXCLUDE.equals(metadata));
MetadataChanges.EXCLUDE.equals(metadata),
snap.hasCachedResults());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void testConstructor() {
boolean hasPendingWrites = true;
boolean syncStateChanges = true;
boolean excludesMetadataChanges = true;
boolean hasCachedResults = false;

ViewSnapshot snapshot =
new ViewSnapshot(
Expand All @@ -59,7 +60,8 @@ public void testConstructor() {
fromCache,
mutatedKeys,
syncStateChanges,
excludesMetadataChanges);
excludesMetadataChanges,
hasCachedResults);

assertEquals(query, snapshot.getQuery());
assertEquals(docs, snapshot.getDocuments());
Expand All @@ -70,5 +72,6 @@ public void testConstructor() {
assertEquals(hasPendingWrites, snapshot.hasPendingWrites());
assertEquals(syncStateChanges, snapshot.didSyncStateChange());
assertEquals(excludesMetadataChanges, snapshot.excludesMetadataChanges());
assertEquals(hasCachedResults, snapshot.hasCachedResults());
}
}