Skip to content

Commit

Permalink
feat(firestore): support for PersistentCacheIndexManager (#7910)
Browse files Browse the repository at this point in the history
  • Loading branch information
russellwheatley authored Aug 13, 2024
1 parent eec08a0 commit 0b0de45
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 1 deletion.
46 changes: 46 additions & 0 deletions packages/firestore/__tests__/firestore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ import firestore, {
deleteDoc,
onSnapshot,
Timestamp,
getPersistentCacheIndexManager,
deleteAllPersistentCacheIndexes,
disablePersistentCacheIndexAutoCreation,
enablePersistentCacheIndexAutoCreation,
} from '../lib';

const COLLECTION = 'firestore';
Expand Down Expand Up @@ -629,5 +633,47 @@ describe('Firestore', function () {
it('`Timestamp` is properly exposed to end user', function () {
expect(Timestamp).toBeDefined();
});

it('`getPersistentCacheIndexManager` is properly exposed to end user', function () {
expect(getPersistentCacheIndexManager).toBeDefined();
const indexManager = getPersistentCacheIndexManager(firebase.firestore());
expect(indexManager!.constructor.name).toEqual('FirestorePersistentCacheIndexManager');
});

it('`deleteAllPersistentCacheIndexes` is properly exposed to end user', function () {
expect(deleteAllPersistentCacheIndexes).toBeDefined();
});

it('`disablePersistentCacheIndexAutoCreation` is properly exposed to end user', function () {
expect(disablePersistentCacheIndexAutoCreation).toBeDefined();
});

it('`enablePersistentCacheIndexAutoCreation` is properly exposed to end user', function () {
expect(enablePersistentCacheIndexAutoCreation).toBeDefined();
});
});

describe('FirestorePersistentCacheIndexManager', function () {
it('is exposed to end user', function () {
const firestore1 = firebase.firestore();
firestore1.settings({ persistence: true });
const indexManager = firestore1.persistentCacheIndexManager();
expect(indexManager).toBeDefined();
expect(indexManager.constructor.name).toEqual('FirestorePersistentCacheIndexManager');

expect(indexManager.enableIndexAutoCreation).toBeInstanceOf(Function);
expect(indexManager.disableIndexAutoCreation).toBeInstanceOf(Function);
expect(indexManager.deleteAllIndexes).toBeInstanceOf(Function);

const firestore2 = firebase.firestore();
firestore2.settings({ persistence: false });

const nullIndexManager = firestore2.persistentCacheIndexManager();

expect(nullIndexManager).toBeNull();

const nullIndexManagerModular = getPersistentCacheIndexManager(firestore2);
expect(nullIndexManagerModular).toBeNull();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static io.invertase.firebase.common.RCTConvertFirebase.toHashMap;
import static io.invertase.firebase.firestore.ReactNativeFirebaseFirestoreCommon.rejectPromiseFirestoreException;
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.createFirestoreKey;
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.getFirestoreForApp;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
Expand All @@ -29,6 +30,7 @@
import com.facebook.react.bridge.WritableMap;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.LoadBundleTaskProgress;
import com.google.firebase.firestore.PersistentCacheIndexManager;
import io.invertase.firebase.common.ReactNativeFirebaseModule;

public class ReactNativeFirebaseFirestoreModule extends ReactNativeFirebaseModule {
Expand Down Expand Up @@ -164,6 +166,33 @@ public void terminate(String appName, String databaseId, Promise promise) {
});
}

@ReactMethod
public void persistenceCacheIndexManager(
String appName, String databaseId, int requestType, Promise promise) {
PersistentCacheIndexManager indexManager =
getFirestoreForApp(appName, databaseId).getPersistentCacheIndexManager();
if (indexManager != null) {
switch (requestType) {
case 0:
indexManager.enableIndexAutoCreation();
break;
case 1:
indexManager.disableIndexAutoCreation();
break;
case 2:
indexManager.deleteAllIndexes();
break;
}
} else {
promise.reject(
"firestore/index-manager-null",
"`PersistentCacheIndexManager` is not available, persistence has not been enabled for"
+ " Firestore");
return;
}
promise.resolve(null);
}

private WritableMap taskProgressToWritableMap(LoadBundleTaskProgress progress) {
WritableMap writableMap = Arguments.createMap();
writableMap.putDouble("bytesLoaded", progress.getBytesLoaded());
Expand Down
188 changes: 187 additions & 1 deletion packages/firestore/e2e/firestore.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ describe('firestore()', function () {

describe('disableNetwork() & enableNetwork()', function () {
it('disables and enables with no errors', async function () {
if (Platform.other) {
if (!(Platform.android || Platform.ios)) {
// Not supported on web lite sdk
return;
}

Expand Down Expand Up @@ -211,6 +212,7 @@ describe('firestore()', function () {
it("handles 'estimate'", async function () {
// TODO(ehesp): Figure out how to call settings on other.
if (Platform.other) {
// Not supported on web lite sdk
return;
}

Expand All @@ -237,6 +239,7 @@ describe('firestore()', function () {
it("handles 'previous'", async function () {
// TODO(ehesp): Figure out how to call settings on other.
if (Platform.other) {
// Not supported on web lite sdk
return;
}

Expand Down Expand Up @@ -331,6 +334,88 @@ describe('firestore()', function () {
});
});
});

describe('FirestorePersistentCacheIndexManager', function () {
describe('if persistence is enabled', function () {
it('should enableIndexAutoCreation()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}

const db = firebase.firestore();
const indexManager = db.persistentCacheIndexManager();
await indexManager.enableIndexAutoCreation();
});

it('should disableIndexAutoCreation()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const db = firebase.firestore();
const indexManager = db.persistentCacheIndexManager();
await indexManager.disableIndexAutoCreation();
});

it('should deleteAllIndexes()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const db = firebase.firestore();
const indexManager = db.persistentCacheIndexManager();
await indexManager.deleteAllIndexes();
});
});

describe('if persistence is disabled', function () {
it('should return `null` when calling `persistentCacheIndexManager()`', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const secondFirestore = firebase.app('secondaryFromNative').firestore();
secondFirestore.settings({ persistence: false });
const indexManager = secondFirestore.persistentCacheIndexManager();
should.equal(indexManager, null);
});
});

describe('macOS should throw exception when calling `persistentCacheIndexManager()`', function () {
it('should throw an exception when calling PersistentCacheIndexManager API', async function () {
if (!Platform.other) {
return;
}
const db = firebase.firestore();
const indexManager = db.persistentCacheIndexManager();

try {
await indexManager.enableIndexAutoCreation();

throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}

try {
await indexManager.deleteAllIndexes();

throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}

try {
await indexManager.disableIndexAutoCreation();

throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}
});
});
});
});

describe('modular', function () {
Expand Down Expand Up @@ -683,5 +768,106 @@ describe('firestore()', function () {
});
});
});

describe('FirestorePersistentCacheIndexManager', function () {
describe('if persistence is enabled', function () {
it('should enableIndexAutoCreation()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const {
getFirestore,
getPersistentCacheIndexManager,
enablePersistentCacheIndexAutoCreation,
} = firestoreModular;
const db = getFirestore();
const indexManager = getPersistentCacheIndexManager(db);
await enablePersistentCacheIndexAutoCreation(indexManager);
});

it('should disableIndexAutoCreation()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const {
getFirestore,
getPersistentCacheIndexManager,
disablePersistentCacheIndexAutoCreation,
} = firestoreModular;
const db = getFirestore();
const indexManager = getPersistentCacheIndexManager(db);
await disablePersistentCacheIndexAutoCreation(indexManager);
});

it('should deleteAllIndexes()', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const { getFirestore, getPersistentCacheIndexManager, deleteAllPersistentCacheIndexes } =
firestoreModular;
const db = getFirestore();
const indexManager = getPersistentCacheIndexManager(db);
await deleteAllPersistentCacheIndexes(indexManager);
});
});

describe('if persistence is disabled', function () {
it('should return `null` when calling `persistentCacheIndexManager()`', async function () {
if (Platform.other) {
// Not supported on web lite sdk
return;
}
const { initializeFirestore, getPersistentCacheIndexManager } = firestoreModular;
const { getApp } = modular;
const app = getApp('secondaryFromNative');
const db = await initializeFirestore(app, { persistence: false });

const indexManager = getPersistentCacheIndexManager(db);
should.equal(indexManager, null);
});
});

describe('macOS should throw exception when calling `persistentCacheIndexManager()`', function () {
it('should throw an exception when calling PersistentCacheIndexManager API', async function () {
if (Platform.android || Platform.ios) {
return;
}
const {
getFirestore,
getPersistentCacheIndexManager,
enablePersistentCacheIndexAutoCreation,
disablePersistentCacheIndexAutoCreation,
deleteAllPersistentCacheIndexes,
} = firestoreModular;

const db = getFirestore();
const indexManager = getPersistentCacheIndexManager(db);

try {
await enablePersistentCacheIndexAutoCreation(indexManager);
throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}

try {
await disablePersistentCacheIndexAutoCreation(indexManager);
throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}

try {
await deleteAllPersistentCacheIndexes(indexManager);
throw new Error('Did not throw an Error.');
} catch (e) {
e.message.should.containEql('Not supported in the lite SDK');
}
});
});
});
});
});
33 changes: 33 additions & 0 deletions packages/firestore/ios/RNFBFirestore/RNFBFirestoreModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#import "RNFBFirestoreModule.h"
#import <React/RCTUtils.h>
#import "FirebaseFirestoreInternal/FIRPersistentCacheIndexManager.h"
#import "RNFBFirestoreCommon.h"
#import "RNFBPreferences.h"

Expand Down Expand Up @@ -207,6 +208,38 @@ + (BOOL)requiresMainQueueSetup {
}];
}

RCT_EXPORT_METHOD(persistenceCacheIndexManager
: (FIRApp *)firebaseApp
: (NSString *)databaseId
: (NSInteger)requestType
: (RCTPromiseResolveBlock)resolve
: (RCTPromiseRejectBlock)reject) {
FIRPersistentCacheIndexManager *persistentCacheIndexManager =
[RNFBFirestoreCommon getFirestoreForApp:firebaseApp databaseId:databaseId]
.persistentCacheIndexManager;

if (persistentCacheIndexManager) {
switch (requestType) {
case 0:
[persistentCacheIndexManager enableIndexAutoCreation];
break;
case 1:
[persistentCacheIndexManager disableIndexAutoCreation];
break;
case 2:
[persistentCacheIndexManager deleteAllIndexes];
break;
}
} else {
reject(@"firestore/index-manager-null",
@"`PersistentCacheIndexManager` is not available, persistence has not been enabled for "
@"Firestore",
nil);
return;
}
resolve(nil);
}

- (NSMutableDictionary *)taskProgressToDictionary:(FIRLoadBundleTaskProgress *)progress {
NSMutableDictionary *progressMap = [[NSMutableDictionary alloc] init];
progressMap[@"bytesLoaded"] = @(progress.bytesLoaded);
Expand Down
Loading

0 comments on commit 0b0de45

Please sign in to comment.