Skip to content

Commit 9894353

Browse files
author
Greg Soltis
authored
Wire up LRU GC (#1925)
* Wire up LRU GC
1 parent c3098d6 commit 9894353

File tree

7 files changed

+47
-14
lines changed

7 files changed

+47
-14
lines changed

Firestore/Source/API/FIRFirestore.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ const DatabaseInfo database_info(*self.databaseID, util::MakeString(_persistence
258258
absl::make_unique<ExecutorLibdispatch>(_settings.dispatchQueue);
259259

260260
_client = [FSTFirestoreClient clientWithDatabaseInfo:database_info
261-
usePersistence:_settings.persistenceEnabled
261+
settings:_settings
262262
credentialsProvider:_credentialsProvider.get()
263263
userExecutor:std::move(userExecutor)
264264
workerDispatchQueue:_workerDispatchQueue];

Firestore/Source/API/FIRFirestoreSettings.mm

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
static NSString *const kDefaultHost = @"firestore.googleapis.com";
2424
static const BOOL kDefaultSSLEnabled = YES;
2525
static const BOOL kDefaultPersistenceEnabled = YES;
26+
static const int64_t kDefaultCacheSizeBytes = 100 * 1024 * 1024;
27+
static const int64_t kMinimumCacheSizeBytes = 1 * 1024 * 1024;
2628
// TODO(b/73820332): flip the default.
2729
static const BOOL kDefaultTimestampsInSnapshotsEnabled = NO;
2830

@@ -35,6 +37,7 @@ - (instancetype)init {
3537
_dispatchQueue = dispatch_get_main_queue();
3638
_persistenceEnabled = kDefaultPersistenceEnabled;
3739
_timestampsInSnapshotsEnabled = kDefaultTimestampsInSnapshotsEnabled;
40+
_cacheSizeBytes = kDefaultCacheSizeBytes;
3841
}
3942
return self;
4043
}
@@ -51,7 +54,8 @@ - (BOOL)isEqual:(id)other {
5154
self.isSSLEnabled == otherSettings.isSSLEnabled &&
5255
self.dispatchQueue == otherSettings.dispatchQueue &&
5356
self.isPersistenceEnabled == otherSettings.isPersistenceEnabled &&
54-
self.timestampsInSnapshotsEnabled == otherSettings.timestampsInSnapshotsEnabled;
57+
self.timestampsInSnapshotsEnabled == otherSettings.timestampsInSnapshotsEnabled &&
58+
self.cacheSizeBytes == otherSettings.cacheSizeBytes;
5559
}
5660

5761
- (NSUInteger)hash {
@@ -60,6 +64,7 @@ - (NSUInteger)hash {
6064
// Ignore the dispatchQueue to avoid having to deal with sizeof(dispatch_queue_t).
6165
result = 31 * result + (self.isPersistenceEnabled ? 1231 : 1237);
6266
result = 31 * result + (self.timestampsInSnapshotsEnabled ? 1231 : 1237);
67+
result = 31 * result + (NSUInteger)self.cacheSizeBytes;
6368
return result;
6469
}
6570

@@ -70,6 +75,7 @@ - (id)copyWithZone:(nullable NSZone *)zone {
7075
copy.dispatchQueue = _dispatchQueue;
7176
copy.persistenceEnabled = _persistenceEnabled;
7277
copy.timestampsInSnapshotsEnabled = _timestampsInSnapshotsEnabled;
78+
copy.cacheSizeBytes = _cacheSizeBytes;
7379
return copy;
7480
}
7581

@@ -93,6 +99,14 @@ - (void)setDispatchQueue:(dispatch_queue_t)dispatchQueue {
9399
_dispatchQueue = dispatchQueue;
94100
}
95101

102+
- (void)setCacheSizeBytes:(int64_t)cacheSizeBytes {
103+
if (cacheSizeBytes != kFIRFirestoreCacheSizeUnlimited &&
104+
cacheSizeBytes < kMinimumCacheSizeBytes) {
105+
FSTThrowInvalidArgument(@"Cache size must be set to at least %i bytes", kMinimumCacheSizeBytes);
106+
}
107+
_cacheSizeBytes = cacheSizeBytes;
108+
}
109+
96110
@end
97111

98112
NS_ASSUME_NONNULL_END

Firestore/Source/Core/FSTFirestoreClient.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
@class FIRDocumentReference;
3131
@class FIRDocumentSnapshot;
32+
@class FIRFirestoreSettings;
3233
@class FIRQuery;
3334
@class FIRQuerySnapshot;
3435
@class FSTDatabaseID;
@@ -56,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN
5657
* All callbacks and events will be triggered on the provided userExecutor.
5758
*/
5859
+ (instancetype)clientWithDatabaseInfo:(const firebase::firestore::core::DatabaseInfo &)databaseInfo
59-
usePersistence:(BOOL)usePersistence
60+
settings:(FIRFirestoreSettings *)settings
6061
credentialsProvider:(firebase::firestore::auth::CredentialsProvider *)
6162
credentialsProvider // no passing ownership
6263
userExecutor:

Firestore/Source/Core/FSTFirestoreClient.mm

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <utility>
2222

2323
#import "FIRFirestoreErrors.h"
24+
#import "FIRFirestoreSettings.h"
2425
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
2526
#import "Firestore/Source/API/FIRDocumentSnapshot+Internal.h"
2627
#import "Firestore/Source/API/FIRQuery+Internal.h"
@@ -75,7 +76,7 @@ @interface FSTFirestoreClient () {
7576
}
7677

7778
- (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
78-
usePersistence:(BOOL)usePersistence
79+
settings:(FIRFirestoreSettings *)settings
7980
credentialsProvider:
8081
(CredentialsProvider *)credentialsProvider // no passing ownership
8182
userExecutor:(std::unique_ptr<Executor>)userExecutor
@@ -115,20 +116,20 @@ - (Executor *)userExecutor {
115116
}
116117

117118
+ (instancetype)clientWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
118-
usePersistence:(BOOL)usePersistence
119+
settings:(FIRFirestoreSettings *)settings
119120
credentialsProvider:
120121
(CredentialsProvider *)credentialsProvider // no passing ownership
121122
userExecutor:(std::unique_ptr<Executor>)userExecutor
122123
workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue {
123124
return [[FSTFirestoreClient alloc] initWithDatabaseInfo:databaseInfo
124-
usePersistence:usePersistence
125+
settings:settings
125126
credentialsProvider:credentialsProvider
126127
userExecutor:std::move(userExecutor)
127128
workerDispatchQueue:workerDispatchQueue];
128129
}
129130

130131
- (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
131-
usePersistence:(BOOL)usePersistence
132+
settings:(FIRFirestoreSettings *)settings
132133
credentialsProvider:
133134
(CredentialsProvider *)credentialsProvider // no passing ownership
134135
userExecutor:(std::unique_ptr<Executor>)userExecutor
@@ -167,21 +168,21 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
167168
// before any subsequently queued work runs.
168169
[_workerDispatchQueue dispatchAsync:^{
169170
User user = userPromise->get_future().get();
170-
[self initializeWithUser:user usePersistence:usePersistence];
171+
[self initializeWithUser:user settings:settings];
171172
}];
172173
}
173174
return self;
174175
}
175176

176-
- (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistence {
177+
- (void)initializeWithUser:(const User &)user settings:(FIRFirestoreSettings *)settings {
177178
// Do all of our initialization on our own dispatch queue.
178179
[self.workerDispatchQueue verifyIsCurrentQueue];
179180
LOG_DEBUG("Initializing. Current user: %s", user.uid());
180181

181182
// Note: The initialization work must all be synchronous (we can't dispatch more work) since
182183
// external write/listen operations could get queued to run before that subsequent work
183184
// completes.
184-
if (usePersistence) {
185+
if (settings.isPersistenceEnabled) {
185186
Path dir = [FSTLevelDB storageDirectoryForDatabaseInfo:*self.databaseInfo
186187
documentsDirectory:[FSTLevelDB documentsDirectory]];
187188

@@ -190,9 +191,10 @@ - (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistenc
190191
FSTLocalSerializer *serializer =
191192
[[FSTLocalSerializer alloc] initWithRemoteSerializer:remoteSerializer];
192193
// TODO(gsoltis): enable LRU GC once API is finalized
193-
FSTLevelDB *ldb = [[FSTLevelDB alloc] initWithDirectory:std::move(dir)
194-
serializer:serializer
195-
lruParams:LruParams::Disabled()];
194+
FSTLevelDB *ldb =
195+
[[FSTLevelDB alloc] initWithDirectory:std::move(dir)
196+
serializer:serializer
197+
lruParams:LruParams::WithCacheSize(settings.cacheSizeBytes)];
196198
_lruDelegate = ldb.referenceDelegate;
197199
_persistence = ldb;
198200
[self scheduleLruGarbageCollection];

Firestore/Source/Local/FSTLRUGarbageCollector.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ struct LruParams {
4444
return LruParams{kFIRFirestoreCacheSizeUnlimited, 0, 0};
4545
}
4646

47+
static LruParams WithCacheSize(int64_t cacheSize) {
48+
LruParams params = Default();
49+
params.minBytesThreshold = cacheSize;
50+
return params;
51+
}
52+
4753
int64_t minBytesThreshold;
4854
int percentileToCollect;
4955
int maximumSequenceNumbersToCollect;

Firestore/Source/Public/FIRFirestoreSettings.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
NS_ASSUME_NONNULL_BEGIN
2020

2121
/** Used to set on-disk cache size to unlimited. Garbage collection will not run. */
22-
extern const int64_t kFIRFirestoreCacheSizeUnlimited;
22+
extern const int64_t kFIRFirestoreCacheSizeUnlimited NS_SWIFT_NAME(FirestoreCacheSizeUnlimited);
2323

2424
/** Settings used to configure a `FIRFirestore` instance. */
2525
NS_SWIFT_NAME(FirestoreSettings)
@@ -64,6 +64,15 @@ NS_SWIFT_NAME(FirestoreSettings)
6464
*/
6565
@property(nonatomic, getter=areTimestampsInSnapshotsEnabled) BOOL timestampsInSnapshotsEnabled;
6666

67+
/**
68+
* Sets the cache size threshold above which the SDK will attempt to collect least-recently-used
69+
* documents. The size is not a guarantee that the cache will stay below that size, only that if
70+
* the cache exceeds the given size, cleanup will be attempted. Cannot be set lower than 1MB.
71+
*
72+
* Set to kFIRFirestoreCacheSizeUnlimited to disable garbage collection entirely.
73+
*/
74+
@property(nonatomic, assign) int64_t cacheSizeBytes;
75+
6776
@end
6877

6978
NS_ASSUME_NONNULL_END

Firestore/Swift/Tests/API/BasicCompileTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func initializeDb() -> Firestore {
6464
settings.host = "localhost"
6565
settings.isPersistenceEnabled = true
6666
settings.areTimestampsInSnapshotsEnabled = true
67+
settings.cacheSizeBytes = FirestoreCacheSizeUnlimited
6768
firestore.settings = settings
6869

6970
return firestore

0 commit comments

Comments
 (0)