Skip to content

Commit 24197b5

Browse files
authored
New cache config API (#4869)
A new set of APIs to config firestore's cache behavior.
1 parent 7375cab commit 24197b5

File tree

14 files changed

+515
-53
lines changed

14 files changed

+515
-53
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Unreleased
22
* [fixed] Fixed stack overflow caused by deeply nested server timestamps (#4702).
3+
* [feature] Add new cache config APIs to customize SDK's cache setup.
34

45
## Kotlin
56
* [feature] Added

firebase-firestore/api.txt

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,10 @@ package com.google.firebase.firestore {
230230
}
231231

232232
public final class FirebaseFirestoreSettings {
233-
method public long getCacheSizeBytes();
233+
method @Nullable public com.google.firebase.firestore.LocalCacheSettings getCacheSettings();
234+
method @Deprecated public long getCacheSizeBytes();
234235
method @NonNull public String getHost();
235-
method public boolean isPersistenceEnabled();
236+
method @Deprecated public boolean isPersistenceEnabled();
236237
method public boolean isSslEnabled();
237238
field public static final long CACHE_SIZE_UNLIMITED = -1L; // 0xffffffffffffffffL
238239
}
@@ -241,13 +242,14 @@ package com.google.firebase.firestore {
241242
ctor public FirebaseFirestoreSettings.Builder();
242243
ctor public FirebaseFirestoreSettings.Builder(@NonNull com.google.firebase.firestore.FirebaseFirestoreSettings);
243244
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings build();
244-
method public long getCacheSizeBytes();
245+
method @Deprecated public long getCacheSizeBytes();
245246
method @NonNull public String getHost();
246-
method public boolean isPersistenceEnabled();
247+
method @Deprecated public boolean isPersistenceEnabled();
247248
method public boolean isSslEnabled();
248-
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setCacheSizeBytes(long);
249+
method @Deprecated @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setCacheSizeBytes(long);
249250
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setHost(@NonNull String);
250-
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setPersistenceEnabled(boolean);
251+
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setLocalCacheSettings(@NonNull com.google.firebase.firestore.LocalCacheSettings);
252+
method @Deprecated @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setPersistenceEnabled(boolean);
251253
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings.Builder setSslEnabled(boolean);
252254
}
253255

@@ -310,6 +312,17 @@ package com.google.firebase.firestore {
310312
enum_constant public static final com.google.firebase.firestore.LoadBundleTaskProgress.TaskState SUCCESS;
311313
}
312314

315+
public interface LocalCacheSettings {
316+
}
317+
318+
public final class MemoryCacheSettings implements com.google.firebase.firestore.LocalCacheSettings {
319+
method @NonNull public static com.google.firebase.firestore.MemoryCacheSettings.Builder newBuilder();
320+
}
321+
322+
public static class MemoryCacheSettings.Builder {
323+
method @NonNull public com.google.firebase.firestore.MemoryCacheSettings build();
324+
}
325+
313326
public enum MetadataChanges {
314327
enum_constant public static final com.google.firebase.firestore.MetadataChanges EXCLUDE;
315328
enum_constant public static final com.google.firebase.firestore.MetadataChanges INCLUDE;
@@ -319,6 +332,16 @@ package com.google.firebase.firestore {
319332
method public void onProgress(@NonNull ProgressT);
320333
}
321334

335+
public final class PersistentCacheSettings implements com.google.firebase.firestore.LocalCacheSettings {
336+
method public long getSizeBytes();
337+
method @NonNull public static com.google.firebase.firestore.PersistentCacheSettings.Builder newBuilder();
338+
}
339+
340+
public static class PersistentCacheSettings.Builder {
341+
method @NonNull public com.google.firebase.firestore.PersistentCacheSettings build();
342+
method @NonNull public com.google.firebase.firestore.PersistentCacheSettings.Builder setSizeBytes(long);
343+
}
344+
322345
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) public @interface PropertyName {
323346
method public abstract String value();
324347
}

firebase-firestore/ktx/api.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
package com.google.firebase.firestore.ktx {
33

44
public final class FirestoreKt {
5-
method public static inline <reified T> kotlinx.coroutines.flow.Flow<? extends T> dataObjects(@NonNull com.google.firebase.firestore.DocumentReference, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
65
method public static inline <reified T> kotlinx.coroutines.flow.Flow<? extends java.util.List<? extends T>> dataObjects(@NonNull com.google.firebase.firestore.Query, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
6+
method public static inline <reified T> kotlinx.coroutines.flow.Flow<? extends T> dataObjects(@NonNull com.google.firebase.firestore.DocumentReference, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
77
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore firestore(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app);
88
method @NonNull public static com.google.firebase.firestore.FirebaseFirestoreSettings firestoreSettings(@NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.firestore.FirebaseFirestoreSettings.Builder,kotlin.Unit> init);
99
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull String field);
1010
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull String field, @NonNull com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior);
1111
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull com.google.firebase.firestore.FieldPath fieldPath);
1212
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull com.google.firebase.firestore.FieldPath fieldPath, @NonNull com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior);
1313
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getFirestore(@NonNull com.google.firebase.ktx.Firebase);
14+
method @NonNull public static com.google.firebase.firestore.MemoryCacheSettings memoryCacheSettings(@NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.firestore.MemoryCacheSettings.Builder,kotlin.Unit> init);
15+
method @NonNull public static com.google.firebase.firestore.PersistentCacheSettings persistentCacheSettings(@NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.firestore.PersistentCacheSettings.Builder,kotlin.Unit> init);
1416
method @NonNull public static kotlinx.coroutines.flow.Flow<com.google.firebase.firestore.DocumentSnapshot> snapshots(@NonNull com.google.firebase.firestore.DocumentReference, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
1517
method @NonNull public static kotlinx.coroutines.flow.Flow<com.google.firebase.firestore.QuerySnapshot> snapshots(@NonNull com.google.firebase.firestore.Query, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
1618
method public static inline <reified T> T toObject(@NonNull com.google.firebase.firestore.DocumentSnapshot);

firebase-firestore/ktx/src/main/kotlin/com/google/firebase/firestore/ktx/Firestore.kt

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,7 @@ import androidx.annotation.Keep
1818
import com.google.firebase.FirebaseApp
1919
import com.google.firebase.components.Component
2020
import com.google.firebase.components.ComponentRegistrar
21-
import com.google.firebase.firestore.DocumentReference
22-
import com.google.firebase.firestore.DocumentSnapshot
23-
import com.google.firebase.firestore.FieldPath
24-
import com.google.firebase.firestore.FirebaseFirestore
25-
import com.google.firebase.firestore.FirebaseFirestoreSettings
26-
import com.google.firebase.firestore.MetadataChanges
27-
import com.google.firebase.firestore.Query
28-
import com.google.firebase.firestore.QueryDocumentSnapshot
29-
import com.google.firebase.firestore.QuerySnapshot
21+
import com.google.firebase.firestore.*
3022
import com.google.firebase.firestore.util.Executors.BACKGROUND_EXECUTOR
3123
import com.google.firebase.ktx.Firebase
3224
import com.google.firebase.platforminfo.LibraryVersionComponent
@@ -184,6 +176,20 @@ fun firestoreSettings(
184176
return builder.build()
185177
}
186178

179+
fun memoryCacheSettings(init: MemoryCacheSettings.Builder.() -> Unit): MemoryCacheSettings {
180+
val builder = MemoryCacheSettings.newBuilder()
181+
builder.init()
182+
return builder.build()
183+
}
184+
185+
fun persistentCacheSettings(
186+
init: PersistentCacheSettings.Builder.() -> Unit
187+
): PersistentCacheSettings {
188+
val builder = PersistentCacheSettings.newBuilder()
189+
builder.init()
190+
return builder.build()
191+
}
192+
187193
internal const val LIBRARY_NAME: String = "fire-fst-ktx"
188194

189195
/** @suppress */

firebase-firestore/ktx/src/test/kotlin/com/google/firebase/firestore/ktx/FirestoreTests.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,29 @@ class FirestoreTests : BaseTestCase() {
101101
assertThat(isSslEnabled).isEqualTo(settings.isSslEnabled)
102102
assertThat(isPersistenceEnabled).isEqualTo(settings.isPersistenceEnabled)
103103
}
104+
105+
@Test
106+
fun `LocalCacheSettings builder works`() {
107+
val host = "http://10.0.2.2:8080"
108+
val isSslEnabled = false
109+
110+
val settings = firestoreSettings {
111+
this.host = host
112+
this.isSslEnabled = isSslEnabled
113+
this.setLocalCacheSettings(persistentCacheSettings { setSizeBytes(1_000_000) })
114+
}
115+
116+
assertThat(host).isEqualTo(settings.host)
117+
assertThat(isSslEnabled).isEqualTo(settings.isSslEnabled)
118+
assertThat(settings.isPersistenceEnabled).isTrue()
119+
assertThat(settings.cacheSizeBytes).isEqualTo(1_000_000)
120+
121+
val otherSettings = firestoreSettings { this.setLocalCacheSettings(memoryCacheSettings {}) }
122+
123+
assertThat(otherSettings.host).isEqualTo(FirebaseFirestoreSettings.DEFAULT_HOST)
124+
assertThat(otherSettings.isSslEnabled).isEqualTo(true)
125+
assertThat(otherSettings.isPersistenceEnabled).isFalse()
126+
}
104127
}
105128

106129
@RunWith(RobolectricTestRunner::class)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ public void testLoadedDocumentsShouldNotBeGarbageCollectedRightAway() throws Exc
176176
// This test really only makes sense with memory persistence, as SQLite persistence only ever
177177
// lazily deletes data
178178
db.setFirestoreSettings(
179-
new FirebaseFirestoreSettings.Builder().setPersistenceEnabled(false).build());
179+
new FirebaseFirestoreSettings.Builder()
180+
.setLocalCacheSettings(MemoryCacheSettings.newBuilder().build())
181+
.build());
180182

181183
InputStream bundle = new ByteArrayInputStream(createBundle());
182184
LoadBundleTask bundleTask = db.loadBundle(bundle); // Test the InputStream overload

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import static org.junit.Assert.assertNotSame;
3636
import static org.junit.Assert.assertNull;
3737
import static org.junit.Assert.assertSame;
38+
import static org.junit.Assert.assertThrows;
3839
import static org.junit.Assert.assertTrue;
3940
import static org.junit.Assert.fail;
4041

@@ -1241,4 +1242,60 @@ public void testPendingWriteTaskResolveWhenOfflineIfThereIsNoPending() {
12411242

12421243
assertTrue(awaitsPendingWrites.isComplete() && awaitsPendingWrites.isSuccessful());
12431244
}
1245+
1246+
@Test
1247+
public void testLegacyCacheConfigForMemoryCache() {
1248+
FirebaseFirestore instance = testFirestore();
1249+
instance.setFirestoreSettings(
1250+
new FirebaseFirestoreSettings.Builder(newTestSettings())
1251+
.setPersistenceEnabled(false)
1252+
.build());
1253+
1254+
waitFor(instance.document("coll/doc").set(map("foo", "bar")));
1255+
1256+
assertThrows(
1257+
RuntimeException.class, () -> waitFor(instance.document("coll/doc").get(Source.CACHE)));
1258+
}
1259+
1260+
@Test
1261+
public void testLegacyCacheConfigForPersistentCache() {
1262+
FirebaseFirestore instance = testFirestore();
1263+
instance.setFirestoreSettings(
1264+
new FirebaseFirestoreSettings.Builder(newTestSettings())
1265+
.setPersistenceEnabled(true)
1266+
.build());
1267+
1268+
waitFor(instance.document("coll/doc").set(map("foo", "bar")));
1269+
1270+
DocumentSnapshot snap = waitFor(instance.document("coll/doc").get(Source.CACHE));
1271+
assertEquals(map("foo", "bar"), snap.getData());
1272+
}
1273+
1274+
@Test
1275+
public void testNewCacheConfigForMemoryCache() {
1276+
FirebaseFirestore instance = testFirestore();
1277+
instance.setFirestoreSettings(
1278+
new FirebaseFirestoreSettings.Builder(newTestSettings())
1279+
.setLocalCacheSettings(MemoryCacheSettings.newBuilder().build())
1280+
.build());
1281+
1282+
waitFor(instance.document("coll/doc").set(map("foo", "bar")));
1283+
1284+
assertThrows(
1285+
RuntimeException.class, () -> waitFor(instance.document("coll/doc").get(Source.CACHE)));
1286+
}
1287+
1288+
@Test
1289+
public void testNewCacheConfigForPersistentCache() {
1290+
FirebaseFirestore instance = testFirestore();
1291+
instance.setFirestoreSettings(
1292+
new FirebaseFirestoreSettings.Builder(newTestSettings())
1293+
.setLocalCacheSettings(PersistentCacheSettings.newBuilder().build())
1294+
.build());
1295+
1296+
waitFor(instance.document("coll/doc").set(map("foo", "bar")));
1297+
1298+
DocumentSnapshot snap = waitFor(instance.document("coll/doc").get(Source.CACHE));
1299+
assertEquals(map("foo", "bar"), snap.getData());
1300+
}
12441301
}

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ public static FirebaseFirestoreSettings newTestSettings() {
179179
FirebaseFirestoreSettings.Builder settings = new FirebaseFirestoreSettings.Builder();
180180
settings.setHost(getFirestoreHost());
181181
settings.setSslEnabled(getSslEnabled());
182-
settings.setPersistenceEnabled(true);
183182
return settings.build();
184183
}
185184

0 commit comments

Comments
 (0)