Skip to content

Commit 2d2faba

Browse files
Merge
2 parents 93b66e5 + 1986969 commit 2d2faba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1035
-350
lines changed

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/DefaultHeartBeatInfo.java

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@
1717
import android.content.Context;
1818
import androidx.annotation.NonNull;
1919
import androidx.annotation.VisibleForTesting;
20-
import com.google.android.gms.tasks.Task;
21-
import com.google.android.gms.tasks.Tasks;
2220
import com.google.firebase.components.Component;
2321
import com.google.firebase.components.Dependency;
2422
import com.google.firebase.components.Lazy;
2523
import com.google.firebase.inject.Provider;
26-
import java.util.ArrayList;
27-
import java.util.List;
2824
import java.util.Set;
2925
import java.util.concurrent.Executor;
3026
import java.util.concurrent.LinkedBlockingQueue;
@@ -80,58 +76,6 @@ private DefaultHeartBeatInfo(Context context, Set<HeartBeatConsumer> consumers)
8076
return HeartBeat.NONE;
8177
}
8278

83-
@Override
84-
public Task<List<HeartBeatResult>> getAndClearStoredHeartBeatInfo() {
85-
return Tasks.call(
86-
backgroundExecutor,
87-
() -> {
88-
ArrayList<HeartBeatResult> heartBeatResults = new ArrayList<>();
89-
boolean shouldSendGlobalHeartBeat = false;
90-
HeartBeatInfoStorage storage = storageProvider.get();
91-
List<SdkHeartBeatResult> sdkHeartBeatResults = storage.getStoredHeartBeats(true);
92-
long lastGlobalHeartBeat = storage.getLastGlobalHeartBeat();
93-
HeartBeat heartBeat;
94-
for (SdkHeartBeatResult sdkHeartBeatResult : sdkHeartBeatResults) {
95-
shouldSendGlobalHeartBeat =
96-
HeartBeatInfoStorage.isSameDateUtc(
97-
lastGlobalHeartBeat, sdkHeartBeatResult.getMillis());
98-
if (shouldSendGlobalHeartBeat) {
99-
heartBeat = HeartBeat.COMBINED;
100-
} else {
101-
heartBeat = HeartBeat.SDK;
102-
}
103-
if (shouldSendGlobalHeartBeat) {
104-
lastGlobalHeartBeat = sdkHeartBeatResult.getMillis();
105-
}
106-
heartBeatResults.add(
107-
HeartBeatResult.create(
108-
sdkHeartBeatResult.getSdkName(), sdkHeartBeatResult.getMillis(), heartBeat));
109-
}
110-
if (lastGlobalHeartBeat > 0) {
111-
storage.updateGlobalHeartBeat(lastGlobalHeartBeat);
112-
}
113-
return heartBeatResults;
114-
});
115-
}
116-
117-
@Override
118-
public Task<Void> storeHeartBeatInfo(@NonNull String heartBeatTag) {
119-
if (consumers.size() <= 0) {
120-
return Tasks.forResult(null);
121-
}
122-
return Tasks.call(
123-
backgroundExecutor,
124-
() -> {
125-
long presentTime = System.currentTimeMillis();
126-
boolean shouldSendSdkHB =
127-
storageProvider.get().shouldSendSdkHeartBeat(heartBeatTag, presentTime);
128-
if (shouldSendSdkHB) {
129-
storageProvider.get().storeHeartBeatInformation(heartBeatTag, presentTime);
130-
}
131-
return null;
132-
});
133-
}
134-
13579
public static @NonNull Component<HeartBeatInfo> component() {
13680
return Component.builder(HeartBeatInfo.class)
13781
.add(Dependency.required(Context.class))

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/HeartBeatInfo.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
package com.google.firebase.heartbeatinfo;
1616

1717
import androidx.annotation.NonNull;
18-
import com.google.android.gms.tasks.Task;
19-
import java.util.List;
2018

2119
/**
2220
* Class provides information about heartbeats.
@@ -49,10 +47,4 @@ public int getCode() {
4947

5048
@NonNull
5149
HeartBeat getHeartBeatCode(@NonNull String heartBeatTag);
52-
53-
@NonNull
54-
Task<Void> storeHeartBeatInfo(@NonNull String heartBeatTag);
55-
56-
@NonNull
57-
Task<List<HeartBeatResult>> getAndClearStoredHeartBeatInfo();
5850
}

firebase-common/src/test/java/com/google/firebase/heartbeatinfo/DefaultHeartBeatInfoTest.java

Lines changed: 0 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,14 @@
1515
package com.google.firebase.heartbeatinfo;
1616

1717
import static com.google.common.truth.Truth.assertThat;
18-
import static org.mockito.ArgumentMatchers.anyBoolean;
1918
import static org.mockito.ArgumentMatchers.anyLong;
2019
import static org.mockito.ArgumentMatchers.anyString;
2120
import static org.mockito.Mockito.mock;
22-
import static org.mockito.Mockito.times;
23-
import static org.mockito.Mockito.verify;
2421
import static org.mockito.Mockito.when;
2522

26-
import java.util.ArrayList;
2723
import java.util.HashSet;
2824
import java.util.List;
2925
import java.util.Set;
30-
import java.util.concurrent.ExecutionException;
3126
import java.util.concurrent.ExecutorService;
3227
import java.util.concurrent.LinkedBlockingQueue;
3328
import java.util.concurrent.ThreadPoolExecutor;
@@ -67,108 +62,6 @@ public void getHeartBeatCode_noHeartBeat() {
6762
assertThat(heartBeatInfo.getHeartBeatCode(testSdk).getCode()).isEqualTo(0);
6863
}
6964

70-
@Test
71-
public void whenNoSource_dontStoreHeartBeat() throws ExecutionException, InterruptedException {
72-
73-
DefaultHeartBeatInfo info = new DefaultHeartBeatInfo(() -> storage, new HashSet<>(), executor);
74-
info.storeHeartBeatInfo(testSdk).addOnCompleteListener(executor, storeOnCompleteListener);
75-
storeOnCompleteListener.await();
76-
verify(storage, times(0)).storeHeartBeatInformation(anyString(), anyLong());
77-
}
78-
79-
@Test
80-
public void storeHeartBeatCode_noHeartBeat() throws ExecutionException, InterruptedException {
81-
when(storage.shouldSendSdkHeartBeat(anyString(), anyLong())).thenReturn(Boolean.FALSE);
82-
when(storage.shouldSendGlobalHeartBeat(anyLong())).thenReturn(Boolean.FALSE);
83-
heartBeatInfo
84-
.storeHeartBeatInfo(testSdk)
85-
.addOnCompleteListener(executor, storeOnCompleteListener);
86-
storeOnCompleteListener.await();
87-
heartBeatInfo
88-
.getAndClearStoredHeartBeatInfo()
89-
.addOnCompleteListener(executor, getOnCompleteListener);
90-
List<HeartBeatResult> result = getOnCompleteListener.await();
91-
assertThat(result.size()).isEqualTo(0);
92-
}
93-
94-
@Test
95-
public void storeHeartBeatCode_sdkButNoGlobalHeartBeat()
96-
throws ExecutionException, InterruptedException {
97-
ArrayList<SdkHeartBeatResult> returnResults = new ArrayList<>();
98-
returnResults.add(SdkHeartBeatResult.create(testSdk, 1000000001));
99-
when(storage.shouldSendSdkHeartBeat(anyString(), anyLong())).thenReturn(Boolean.TRUE);
100-
when(storage.shouldSendGlobalHeartBeat(anyLong())).thenReturn(Boolean.FALSE);
101-
when(storage.getLastGlobalHeartBeat()).thenReturn((long) 1000000000);
102-
when(storage.getStoredHeartBeats(anyBoolean())).thenReturn(returnResults);
103-
heartBeatInfo
104-
.storeHeartBeatInfo(testSdk)
105-
.addOnCompleteListener(executor, storeOnCompleteListener);
106-
storeOnCompleteListener.await();
107-
heartBeatInfo
108-
.getAndClearStoredHeartBeatInfo()
109-
.addOnCompleteListener(executor, getOnCompleteListener);
110-
List<HeartBeatResult> results = getOnCompleteListener.await();
111-
verify(storage, times(1)).storeHeartBeatInformation(anyString(), anyLong());
112-
assertThat(results.size()).isEqualTo(1);
113-
assertThat(results.get(0))
114-
.isEqualTo(HeartBeatResult.create(testSdk, 1000000001, HeartBeatInfo.HeartBeat.SDK));
115-
verify(storage, times(1)).updateGlobalHeartBeat(1000000000);
116-
}
117-
118-
@Test
119-
public void storeHeartBeatCode_globalAndSDKHeartBeat()
120-
throws ExecutionException, InterruptedException {
121-
ArrayList<SdkHeartBeatResult> returnResults = new ArrayList<>();
122-
returnResults.add(SdkHeartBeatResult.create(testSdk, 100000000));
123-
when(storage.shouldSendSdkHeartBeat(anyString(), anyLong())).thenReturn(Boolean.TRUE);
124-
when(storage.shouldSendGlobalHeartBeat(anyLong())).thenReturn(Boolean.TRUE);
125-
when(storage.getLastGlobalHeartBeat()).thenReturn((long) 0);
126-
when(storage.getStoredHeartBeats(anyBoolean())).thenReturn(returnResults);
127-
heartBeatInfo
128-
.storeHeartBeatInfo(testSdk)
129-
.addOnCompleteListener(executor, storeOnCompleteListener);
130-
storeOnCompleteListener.await();
131-
heartBeatInfo
132-
.getAndClearStoredHeartBeatInfo()
133-
.addOnCompleteListener(executor, getOnCompleteListener);
134-
List<HeartBeatResult> results = getOnCompleteListener.await();
135-
verify(storage, times(1)).storeHeartBeatInformation(anyString(), anyLong());
136-
assertThat(results.size()).isEqualTo(1);
137-
assertThat(results.get(0))
138-
.isEqualTo(HeartBeatResult.create(testSdk, 100000000, HeartBeatInfo.HeartBeat.COMBINED));
139-
verify(storage, times(1)).updateGlobalHeartBeat(100000000);
140-
}
141-
142-
@Test
143-
public void storeHeartBeatCode_ThreeHeartBeats() throws ExecutionException, InterruptedException {
144-
ArrayList<SdkHeartBeatResult> returnResults = new ArrayList<>();
145-
returnResults.add(SdkHeartBeatResult.create(testSdk, 100000000));
146-
returnResults.add(SdkHeartBeatResult.create(testSdk, 200000000));
147-
returnResults.add(SdkHeartBeatResult.create(testSdk, 200002000));
148-
when(storage.shouldSendSdkHeartBeat(anyString(), anyLong())).thenReturn(Boolean.TRUE);
149-
when(storage.shouldSendGlobalHeartBeat(anyLong())).thenReturn(Boolean.TRUE);
150-
when(storage.getLastGlobalHeartBeat()).thenReturn((long) 0);
151-
when(storage.getStoredHeartBeats(anyBoolean())).thenReturn(returnResults);
152-
153-
heartBeatInfo
154-
.storeHeartBeatInfo(testSdk)
155-
.addOnCompleteListener(executor, storeOnCompleteListener);
156-
storeOnCompleteListener.await();
157-
heartBeatInfo
158-
.getAndClearStoredHeartBeatInfo()
159-
.addOnCompleteListener(executor, getOnCompleteListener);
160-
List<HeartBeatResult> results = getOnCompleteListener.await();
161-
verify(storage, times(1)).storeHeartBeatInformation(anyString(), anyLong());
162-
assertThat(results.size()).isEqualTo(3);
163-
assertThat(results.get(0))
164-
.isEqualTo(HeartBeatResult.create(testSdk, 100000000, HeartBeatInfo.HeartBeat.COMBINED));
165-
assertThat(results.get(1))
166-
.isEqualTo(HeartBeatResult.create(testSdk, 200000000, HeartBeatInfo.HeartBeat.COMBINED));
167-
assertThat(results.get(2))
168-
.isEqualTo(HeartBeatResult.create(testSdk, 200002000, HeartBeatInfo.HeartBeat.SDK));
169-
verify(storage, times(1)).updateGlobalHeartBeat(200000000);
170-
}
171-
17265
@Test
17366
public void getHeartBeatCode_sdkHeartBeat() {
17467
when(storage.shouldSendSdkHeartBeat(anyString(), anyLong())).thenReturn(Boolean.TRUE);

firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java

Lines changed: 22 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -88,54 +88,13 @@ IndexManager getIndexManager() {
8888
* for it.
8989
*/
9090
Document getDocument(DocumentKey key) {
91-
if (Persistence.OVERLAY_SUPPORT_ENABLED) {
92-
Mutation overlay = documentOverlayCache.getOverlay(key);
93-
MutableDocument fromOverlay = remoteDocumentCache.get(key);
94-
if (overlay != null) {
95-
overlay.applyToLocalView(fromOverlay, null, Timestamp.now());
96-
}
97-
98-
// TODO(Overlay): Remove below and just return `fromOverlay`.
99-
List<MutationBatch> batches = mutationQueue.getAllMutationBatchesAffectingDocumentKey(key);
100-
Document fromMutationQueue = getDocument(key, batches);
101-
hardAssert(
102-
fromOverlay.equals(fromMutationQueue),
103-
"Document from overlay does not match mutation queue");
104-
105-
return fromOverlay;
106-
}
107-
List<MutationBatch> batches = mutationQueue.getAllMutationBatchesAffectingDocumentKey(key);
108-
return getDocument(key, batches);
109-
}
110-
111-
// Internal version of {@code getDocument} that allows reusing batches.
112-
private Document getDocument(DocumentKey key, List<MutationBatch> inBatches) {
113-
MutableDocument document = remoteDocumentCache.get(key);
114-
for (MutationBatch batch : inBatches) {
115-
batch.applyToLocalView(document);
116-
}
117-
return document;
118-
}
119-
120-
/**
121-
* Applies the given {@code batches} to the given {@code docs}. The docs are updated to reflect
122-
* the contents of the mutations.
123-
*
124-
* <p>Returns a {@link DocumentKey} to {@link FieldMask} map, representing the fields mutated for
125-
* each document. This is useful to build overlays.
126-
*/
127-
private Map<DocumentKey, FieldMask> applyLocalMutationsToDocuments(
128-
Map<DocumentKey, MutableDocument> docs, List<MutationBatch> batches) {
129-
Map<DocumentKey, FieldMask> changedMasks = new HashMap<>();
130-
for (Map.Entry<DocumentKey, MutableDocument> base : docs.entrySet()) {
131-
FieldMask mask = null;
132-
for (MutationBatch batch : batches) {
133-
mask = batch.applyToLocalView(base.getValue(), mask);
134-
}
135-
changedMasks.put(base.getKey(), mask);
91+
Mutation overlay = documentOverlayCache.getOverlay(key);
92+
MutableDocument fromOverlay = remoteDocumentCache.get(key);
93+
if (overlay != null) {
94+
overlay.applyToLocalView(fromOverlay, null, Timestamp.now());
13695
}
13796

138-
return changedMasks;
97+
return fromOverlay;
13998
}
14099

141100
/**
@@ -160,31 +119,25 @@ ImmutableSortedMap<DocumentKey, Document> getDocuments(Iterable<DocumentKey> key
160119
ImmutableSortedMap<DocumentKey, Document> getLocalViewOfDocuments(
161120
Map<DocumentKey, MutableDocument> docs, Set<DocumentKey> existenceStateChanged) {
162121
ImmutableSortedMap<DocumentKey, Document> results = emptyDocumentMap();
163-
if (Persistence.OVERLAY_SUPPORT_ENABLED) {
164-
Map<DocumentKey, MutableDocument> recalculateDocuments = new HashMap<>();
165-
for (Map.Entry<DocumentKey, MutableDocument> entry : docs.entrySet()) {
166-
Mutation overlay = documentOverlayCache.getOverlay(entry.getKey());
167-
// Recalculate an overlay if the document's existence state is changed due to a remote
168-
// event *and* the overlay is a PatchMutation. This is because document existence state
169-
// can change if some patch mutation's preconditions are met.
170-
// NOTE: we recalculate when `overlay` is null as well, because there might be a patch
171-
// mutation whose precondition does not match before the change (hence overlay==null),
172-
// but would now match.
173-
if (existenceStateChanged.contains(entry.getKey())
174-
&& (overlay == null || overlay instanceof PatchMutation)) {
175-
recalculateDocuments.put(entry.getKey(), docs.get(entry.getKey()));
176-
} else if (overlay != null) {
177-
overlay.applyToLocalView(entry.getValue(), null, Timestamp.now());
178-
}
122+
Map<DocumentKey, MutableDocument> recalculateDocuments = new HashMap<>();
123+
for (Map.Entry<DocumentKey, MutableDocument> entry : docs.entrySet()) {
124+
Mutation overlay = documentOverlayCache.getOverlay(entry.getKey());
125+
// Recalculate an overlay if the document's existence state is changed due to a remote
126+
// event *and* the overlay is a PatchMutation. This is because document existence state
127+
// can change if some patch mutation's preconditions are met.
128+
// NOTE: we recalculate when `overlay` is null as well, because there might be a patch
129+
// mutation whose precondition does not match before the change (hence overlay==null),
130+
// but would now match.
131+
if (existenceStateChanged.contains(entry.getKey())
132+
&& (overlay == null || overlay instanceof PatchMutation)) {
133+
recalculateDocuments.put(entry.getKey(), docs.get(entry.getKey()));
134+
} else if (overlay != null) {
135+
overlay.applyToLocalView(entry.getValue(), null, Timestamp.now());
179136
}
180-
181-
recalculateAndSaveOverlays(recalculateDocuments);
182-
} else {
183-
List<MutationBatch> batches =
184-
mutationQueue.getAllMutationBatchesAffectingDocumentKeys(docs.keySet());
185-
applyLocalMutationsToDocuments(docs, batches);
186137
}
187138

139+
recalculateAndSaveOverlays(recalculateDocuments);
140+
188141
for (Map.Entry<DocumentKey, MutableDocument> entry : docs.entrySet()) {
189142
results = results.insert(entry.getKey(), entry.getValue());
190143
}
@@ -298,31 +251,9 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
298251
return results;
299252
}
300253

254+
/** Queries the remote documents and overlays by doing a full collection scan. */
301255
private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollectionQuery(
302256
Query query, IndexOffset offset) {
303-
if (Persistence.OVERLAY_SUPPORT_ENABLED) {
304-
// TODO(Overlay): Remove the assert and just return `fromOverlay`.
305-
ImmutableSortedMap<DocumentKey, Document> fromOverlay =
306-
getDocumentsMatchingCollectionQueryFromOverlayCache(query, offset);
307-
// TODO(Overlay): Delete below before merging. The code passes, but there are tests
308-
// looking at how many documents read from remote document, and this would double
309-
// the count.
310-
/*
311-
ImmutableSortedMap<DocumentKey, Document> fromMutationQueue =
312-
getDocumentsMatchingCollectionQueryFromMutationQueue(query, sinceReadTime);
313-
hardAssert(
314-
fromOverlay.equals(fromMutationQueue),
315-
"Documents from overlay do not match mutation queue version.");
316-
*/
317-
return fromOverlay;
318-
} else {
319-
return getDocumentsMatchingCollectionQueryFromMutationQueue(query, offset);
320-
}
321-
}
322-
323-
/** Queries the remote documents and overlays by doing a full collection scan. */
324-
private ImmutableSortedMap<DocumentKey, Document>
325-
getDocumentsMatchingCollectionQueryFromOverlayCache(Query query, IndexOffset offset) {
326257
Map<DocumentKey, MutableDocument> remoteDocuments =
327258
remoteDocumentCache.getAll(query.getPath(), offset);
328259
Map<DocumentKey, Mutation> overlays = documentOverlayCache.getOverlays(query.getPath(), -1);

0 commit comments

Comments
 (0)