Skip to content

Commit ec2abdb

Browse files
Random changes for Indexing (#3169)
1 parent 4231f58 commit ec2abdb

File tree

6 files changed

+42
-59
lines changed

6 files changed

+42
-59
lines changed

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/IndexingTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ public void tearDown() {
4949
}
5050

5151
@Test
52-
public void testCanConfigureIndices() throws ExecutionException, InterruptedException {
52+
public void testCanConfigureIndexes() throws ExecutionException, InterruptedException {
5353
FirebaseFirestore db = testFirestore();
5454
Task<Void> indexTask =
55-
db.configureIndices(
55+
db.setIndexConfiguration(
5656
"{\n"
5757
+ " \"indexes\": [\n"
5858
+ " {\n"
@@ -89,7 +89,7 @@ public void testCanConfigureIndices() throws ExecutionException, InterruptedExce
8989
public void testBadJsonDoesNotCrashClient() {
9090
FirebaseFirestore db = testFirestore();
9191

92-
Assert.assertThrows(IllegalArgumentException.class, () -> db.configureIndices("{,"));
92+
Assert.assertThrows(IllegalArgumentException.class, () -> db.setIndexConfiguration("{,"));
9393
}
9494

9595
@Test
@@ -98,7 +98,7 @@ public void testBadIndexDoesNotCrashClient() {
9898
Assert.assertThrows(
9999
IllegalArgumentException.class,
100100
() ->
101-
db.configureIndices(
101+
db.setIndexConfiguration(
102102
"{\n"
103103
+ " \"indexes\": [\n"
104104
+ " {\n"

firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,14 @@ public FirebaseApp getApp() {
297297
* automatically start using the index once the index entries have been written.
298298
*
299299
* <p>The method accepts the JSON format exported by the Firebase CLI (`firebase
300-
* firestore:indexes`). If the JSON format is invalid, this method rejects the returned task.
300+
* firestore:indexes`). If the JSON format is invalid, this method throws an exception.
301301
*
302302
* @param json The JSON format exported by the Firebase CLI.
303303
* @return A task that resolves once all indices are successfully configured.
304+
* @throws IllegalArgumentException if the JSON format is invalid
304305
*/
305306
@VisibleForTesting
306-
Task<Void> configureIndices(String json) {
307+
Task<Void> setIndexConfiguration(String json) {
307308
ensureClientConfigured();
308309

309310
// Preconditions.checkState(BuildConfig.ENABLE_INDEXING, "Indexing support is not yet

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

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.firebase.firestore.model.ResourcePath;
2727
import com.google.firebase.firestore.model.SnapshotVersion;
2828
import com.google.firebase.firestore.util.AsyncQueue;
29+
import com.google.firebase.firestore.util.Logger;
2930
import java.util.ArrayList;
3031
import java.util.Collection;
3132
import java.util.Collections;
@@ -37,6 +38,8 @@
3738

3839
/** Implements the steps for backfilling indexes. */
3940
public class IndexBackfiller {
41+
private static final String LOG_TAG = "IndexBackfiller";
42+
4043
/** How long we wait to try running index backfill after SDK initialization. */
4144
private static final long INITIAL_BACKFILL_DELAY_MS = TimeUnit.SECONDS.toMillis(15);
4245
/** Minimum amount of time between backfill checks, after the first one. */
@@ -65,29 +68,6 @@ public void setIndexManager(IndexManager indexManager) {
6568
this.indexManager = indexManager;
6669
}
6770

68-
public static class Results {
69-
private final boolean hasRun;
70-
71-
private final int documentsProcessed;
72-
73-
static IndexBackfiller.Results DidNotRun() {
74-
return new IndexBackfiller.Results(/* hasRun= */ false, 0);
75-
}
76-
77-
Results(boolean hasRun, int documentsProcessed) {
78-
this.hasRun = hasRun;
79-
this.documentsProcessed = documentsProcessed;
80-
}
81-
82-
public boolean hasRun() {
83-
return hasRun;
84-
}
85-
86-
public int getDocumentsProcessed() {
87-
return documentsProcessed;
88-
}
89-
}
90-
9171
public class Scheduler implements com.google.firebase.firestore.local.Scheduler {
9272
private boolean hasRun = false;
9373
@Nullable private AsyncQueue.DelayedTask backfillTask;
@@ -118,7 +98,8 @@ private void scheduleBackfill() {
11898
AsyncQueue.TimerId.INDEX_BACKFILL,
11999
delay,
120100
() -> {
121-
backfill();
101+
int documentsProcessed = backfill();
102+
Logger.debug(LOG_TAG, "Documents written: %s", documentsProcessed);
122103
hasRun = true;
123104
scheduleBackfill();
124105
});
@@ -129,15 +110,12 @@ public Scheduler getScheduler() {
129110
return scheduler;
130111
}
131112

132-
public Results backfill() {
113+
/** Runs a single backfill operation and returns the number of documents processed. */
114+
public int backfill() {
133115
hardAssert(localDocumentsView != null, "setLocalDocumentsView() not called");
134116
hardAssert(indexManager != null, "setIndexManager() not called");
135117
return persistence.runTransaction(
136-
"Backfill Indexes",
137-
() -> {
138-
int documentsProcessed = writeIndexEntries(localDocumentsView);
139-
return new Results(/* hasRun= */ true, documentsProcessed);
140-
});
118+
"Backfill Indexes", () -> writeIndexEntries(localDocumentsView));
141119
}
142120

143121
/** Writes index entries until the cap is reached. Returns the number of documents processed. */
@@ -149,6 +127,7 @@ private int writeIndexEntries(LocalDocumentsView localDocumentsView) {
149127
if (collectionGroup == null || processedCollectionGroups.contains(collectionGroup)) {
150128
break;
151129
}
130+
Logger.debug(LOG_TAG, "Processing collection: %s", collectionGroup);
152131
documentsRemaining -=
153132
writeEntriesForCollectionGroup(localDocumentsView, collectionGroup, documentsRemaining);
154133
processedCollectionGroups.add(collectionGroup);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public final class LocalStore implements BundleCallback {
130130
private LocalDocumentsView localDocuments;
131131

132132
/** Performs queries over the localDocuments (and potentially maintains indexes). */
133-
private QueryEngine queryEngine;
133+
private final QueryEngine queryEngine;
134134

135135
/** The set of document references maintained by any local views. */
136136
private final ReferenceSet localViewReferences;
@@ -170,6 +170,7 @@ public LocalStore(
170170
this.queryEngine = queryEngine;
171171
this.indexBackfiller = indexBackfiller;
172172
queryEngine.setLocalDocumentsView(localDocuments);
173+
queryEngine.setIndexManager(indexManager);
173174

174175
localViewReferences = new ReferenceSet();
175176
persistence.getReferenceDelegate().setInMemoryPins(localViewReferences);

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,11 @@ private void createV1RemoteDocumentCache() {
358358
* <p>The `index_configuration` table holds the configuration for all indices. Entries in this
359359
* table apply for all users. It is not possible to only enable indices for a subset of users.
360360
*
361+
* <p>The `index_state` table holds backfill information on each index that stores when it was
362+
* last updated.
363+
*
361364
* <p>The `index_entries` table holds the index values themselves. An index value is created for
362-
* each field combination that matches a configured index. If there are pending mutations that
363-
* affect an indexed field, an additional index entry is created per mutated field.
365+
* each field combination that matches a configured index.
364366
*/
365367
private void createFieldIndex() {
366368
ifTablesDontExist(

firebase-firestore/src/test/java/com/google/firebase/firestore/local/IndexBackfillerTest.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public void testBackfillWritesLatestReadTimeToFieldIndexOnCompletion() {
9999
addDoc("coll1/docA", "foo", version(10));
100100
addDoc("coll2/docA", "bar", version(20));
101101

102-
IndexBackfiller.Results results = backfiller.backfill();
103-
assertEquals(2, results.getDocumentsProcessed());
102+
int documentsProcessed = backfiller.backfill();
103+
assertEquals(2, documentsProcessed);
104104

105105
FieldIndex fieldIndex1 = indexManager.getFieldIndexes("coll1").iterator().next();
106106
FieldIndex fieldIndex2 = indexManager.getFieldIndexes("coll2").iterator().next();
@@ -112,8 +112,8 @@ public void testBackfillWritesLatestReadTimeToFieldIndexOnCompletion() {
112112
addDoc("coll2/docB", "bar", version(60));
113113
addDoc("coll2/docC", "bar", version(60, 10));
114114

115-
results = backfiller.backfill();
116-
assertEquals(4, results.getDocumentsProcessed());
115+
documentsProcessed = backfiller.backfill();
116+
assertEquals(4, documentsProcessed);
117117

118118
fieldIndex1 = indexManager.getFieldIndexes("coll1").iterator().next();
119119
fieldIndex2 = indexManager.getFieldIndexes("coll2").iterator().next();
@@ -127,17 +127,17 @@ public void testBackfillFetchesDocumentsAfterEarliestReadTime() {
127127

128128
// Documents before earliest read time should not be fetched.
129129
addDoc("coll1/docA", "foo", version(9));
130-
IndexBackfiller.Results results = backfiller.backfill();
131-
assertEquals(0, results.getDocumentsProcessed());
130+
int documentsProcessed = backfiller.backfill();
131+
assertEquals(0, documentsProcessed);
132132

133133
// Read time of index should not change.
134134
Iterator<FieldIndex> it = indexManager.getFieldIndexes("coll1").iterator();
135135
assertEquals(version(10), it.next().getIndexState().getReadTime());
136136

137137
// Documents that are after the earliest read time but before field index read time are fetched.
138138
addDoc("coll1/docB", "boo", version(19));
139-
results = backfiller.backfill();
140-
assertEquals(1, results.getDocumentsProcessed());
139+
documentsProcessed = backfiller.backfill();
140+
assertEquals(1, documentsProcessed);
141141

142142
// Field indexes should now hold the latest read time
143143
it = indexManager.getFieldIndexes("coll1").iterator();
@@ -153,8 +153,8 @@ public void testBackfillWritesIndexEntries() {
153153
addDoc("coll2/docA", "bar", version(10));
154154
addDoc("coll2/docB", "car", version(10));
155155

156-
IndexBackfiller.Results results = backfiller.backfill();
157-
assertEquals(4, results.getDocumentsProcessed());
156+
int documentsProcessed = backfiller.backfill();
157+
assertEquals(4, documentsProcessed);
158158
}
159159

160160
@Test
@@ -167,13 +167,13 @@ public void testBackfillWritesOldestDocumentFirst() {
167167
addDoc("coll1/docB", "foo", version(3));
168168
addDoc("coll1/docC", "foo", version(10));
169169

170-
IndexBackfiller.Results results = backfiller.backfill();
171-
assertEquals(2, results.getDocumentsProcessed());
170+
int documentsProcessed = backfiller.backfill();
171+
assertEquals(2, documentsProcessed);
172172

173173
verifyQueryResults("coll1", "coll1/docA", "coll1/docB");
174174

175-
results = backfiller.backfill();
176-
assertEquals(1, results.getDocumentsProcessed());
175+
documentsProcessed = backfiller.backfill();
176+
assertEquals(1, documentsProcessed);
177177

178178
verifyQueryResults("coll1", "coll1/docA", "coll1/docB", "coll1/docC");
179179
}
@@ -192,8 +192,8 @@ public void testBackfillUpdatesCollectionGroups() {
192192
String collectionGroup = indexManager.getNextCollectionGroupToUpdate();
193193
assertEquals("coll1", collectionGroup);
194194

195-
IndexBackfiller.Results results = backfiller.backfill();
196-
assertEquals(2, results.getDocumentsProcessed());
195+
int documentsProcessed = backfiller.backfill();
196+
assertEquals(2, documentsProcessed);
197197

198198
// Check that coll1 was backfilled and that coll2 is next
199199
collectionGroup = indexManager.getNextCollectionGroupToUpdate();
@@ -217,8 +217,8 @@ public void testBackfillPrioritizesNewCollectionGroups() {
217217
// Check that coll3 is the next collection ID the backfiller should update
218218
assertEquals("coll3", indexManager.getNextCollectionGroupToUpdate());
219219

220-
IndexBackfiller.Results results = backfiller.backfill();
221-
assertEquals(1, results.getDocumentsProcessed());
220+
int documentsProcessed = backfiller.backfill();
221+
assertEquals(1, documentsProcessed);
222222

223223
verifyQueryResults("coll3", "coll3/doc");
224224
}
@@ -233,8 +233,8 @@ public void testBackfillWritesUntilCap() {
233233
addDoc("coll2/docA", "foo", version(30));
234234
addDoc("coll2/docA", "foo", version(40));
235235

236-
IndexBackfiller.Results results = backfiller.backfill();
237-
assertEquals(3, results.getDocumentsProcessed());
236+
int documentsProcessed = backfiller.backfill();
237+
assertEquals(3, documentsProcessed);
238238

239239
verifyQueryResults("coll1", "coll1/docA", "coll1/docB");
240240
verifyQueryResults("coll2", "coll2/docA");

0 commit comments

Comments
 (0)