Skip to content

Commit 962ce7f

Browse files
committed
WIP - working on firestore multidb issues - not working but this is current status
1 parent ff53e9e commit 962ce7f

3 files changed

Lines changed: 165 additions & 2626 deletions

File tree

packages/firestore/android/src/main/java/io/invertase/firebase/firestore/UniversalFirebaseFirestoreCommon.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,63 @@ static String createFirestoreKey(String appName, String databaseId) {
3737

3838
static FirebaseFirestore getFirestoreForApp(String appName, String databaseId) {
3939
String firestoreKey = createFirestoreKey(appName, databaseId);
40-
WeakReference<FirebaseFirestore> cachedInstance = instanceCache.get(firestoreKey);
40+
System.err.println(
41+
"RNFB_FIRESTORE_CACHE_TRACE ENTER thread="
42+
+ Thread.currentThread().getName()
43+
+ " appName="
44+
+ appName
45+
+ " databaseId="
46+
+ databaseId
47+
+ " lookupKey(firestoreKey)="
48+
+ firestoreKey
49+
+ " mapSize="
50+
+ instanceCache.size());
4151

52+
WeakReference<FirebaseFirestore> cachedInstance = instanceCache.get(firestoreKey);
4253
if (cachedInstance != null) {
43-
return cachedInstance.get();
54+
FirebaseFirestore resolved = cachedInstance.get();
55+
System.err.println(
56+
"RNFB_FIRESTORE_CACHE_TRACE CACHE_HIT lookupKey="
57+
+ firestoreKey
58+
+ " weakRefNonNull=true resolvedNonNull="
59+
+ (resolved != null)
60+
+ " identityHash="
61+
+ (resolved != null ? System.identityHashCode(resolved) : -1));
62+
return resolved;
4463
}
4564

65+
System.err.println(
66+
"RNFB_FIRESTORE_CACHE_TRACE CACHE_MISS lookupKey="
67+
+ firestoreKey
68+
+ " (no entry for composite key; note put() uses appName only, not firestoreKey)");
69+
4670
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
4771
FirestoreChannel.setClientLanguage("gl-rn/" + ReactNativeFirebaseVersion.VERSION);
4872

4973
FirebaseFirestore instance = FirebaseFirestore.getInstance(firebaseApp, databaseId);
5074

5175
setFirestoreSettings(instance, firestoreKey);
5276

77+
System.err.println(
78+
"RNFB_FIRESTORE_CACHE_TRACE PUT keyUsedForPut=APP_NAME_ONLY("
79+
+ appName
80+
+ ") NOT firestoreKey("
81+
+ firestoreKey
82+
+ ") newInstanceIdentityHash="
83+
+ System.identityHashCode(instance));
84+
5385
instanceCache.put(appName, new WeakReference<FirebaseFirestore>(instance));
5486

87+
WeakReference<FirebaseFirestore> wrongKeyProbe = instanceCache.get(firestoreKey);
88+
WeakReference<FirebaseFirestore> appNameProbe = instanceCache.get(appName);
89+
System.err.println(
90+
"RNFB_FIRESTORE_CACHE_TRACE POST_PUT get(firestoreKey)="
91+
+ (wrongKeyProbe != null)
92+
+ " get(appName)="
93+
+ (appNameProbe != null)
94+
+ " mapSize="
95+
+ instanceCache.size());
96+
5597
return instance;
5698
}
5799

packages/firestore/e2e/SecondDatabase/second.where.e2e.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,127 @@ const COLLECTION = 'second-database';
2121
const SECOND_DATABASE_ID = 'second-rnfb';
2222

2323
describe('Second Database', function () {
24+
describe.only('getFirestore (same default app, multiple databaseIds)', function () {
25+
describe('modular', function () {
26+
beforeEach(async function () {
27+
await wipe(false, '(default)');
28+
await wipe(false, SECOND_DATABASE_ID);
29+
});
30+
31+
it('returns distinct Firestore instances per databaseId (customUrlOrRegion)', function () {
32+
const { getApp } = modular;
33+
const { getFirestore } = firestoreModular;
34+
const app = getApp();
35+
const dbDefault = getFirestore(app, '(default)');
36+
const dbSecond = getFirestore(app, SECOND_DATABASE_ID);
37+
38+
dbDefault.app.name.should.equal(dbSecond.app.name);
39+
dbDefault.customUrlOrRegion.should.equal('(default)');
40+
dbSecond.customUrlOrRegion.should.equal(SECOND_DATABASE_ID);
41+
});
42+
43+
// Probes Android native cache in UniversalFirebaseFirestoreCommon (must key by app:databaseId).
44+
// Uses the same emulator DB ids and wipe pattern as the rest of this directory.
45+
it('isolates reads and writes per databaseId on Android', async function () {
46+
if (!Platform.android) {
47+
return;
48+
}
49+
const { getApp } = modular;
50+
const { getFirestore, doc, setDoc, getDoc, deleteDoc } = firestoreModular;
51+
52+
const app = getApp();
53+
const dbDefault = getFirestore(app, '(default)');
54+
const dbSecond = getFirestore(app, SECOND_DATABASE_ID);
55+
56+
const pathDefault = 'firestore/multiDbIdentityProbe';
57+
const pathSecond = `${COLLECTION}/multiDbIdentityProbe`;
58+
59+
await setDoc(doc(dbDefault, pathDefault), { marker: 'default-db' });
60+
await setDoc(doc(dbSecond, pathSecond), { marker: 'second-db' });
61+
62+
(await getDoc(doc(dbDefault, pathDefault))).data().marker.should.eql('default-db');
63+
(await getDoc(doc(dbSecond, pathSecond))).data().marker.should.eql('second-db');
64+
65+
await deleteDoc(doc(dbDefault, pathDefault));
66+
await deleteDoc(doc(dbSecond, pathSecond));
67+
});
68+
69+
// The broken map never stores entries under the composite firestoreKey, so CACHE_HIT on that key
70+
// does not happen from getFirestoreForApp alone — simple read/write often still goes through
71+
// FirebaseFirestore.getInstance and looks correct. These cases stress other paths: non-thread-safe
72+
// WeakHashMap under parallel native calls, and terminate() which tries to remove(firestoreKey) but
73+
// never matches entries stored under appName only.
74+
it('stress: many parallel writes to both databases (Android)', async function () {
75+
if (!Platform.android) {
76+
return;
77+
}
78+
const { getApp } = modular;
79+
const { getFirestore, doc, setDoc, getDoc, deleteDoc } = firestoreModular;
80+
const app = getApp();
81+
const dbDefault = getFirestore(app, '(default)');
82+
const dbSecond = getFirestore(app, SECOND_DATABASE_ID);
83+
84+
// Two path segments each: rules allow `firestore/{document=**}` and
85+
// `second-database/{document=**}` when database is second-rnfb. Deeper paths like
86+
// `second-database/cacheStress/0` are not valid document paths (odd segment count).
87+
const n = 25;
88+
const batch = [];
89+
for (let i = 0; i < n; i++) {
90+
batch.push(
91+
setDoc(doc(dbDefault, `firestore/cacheStressDoc_${i}`), { db: 'default', i }),
92+
setDoc(doc(dbSecond, `${COLLECTION}/cacheStressDoc_${i}`), { db: 'second', i }),
93+
);
94+
}
95+
await Promise.all(batch);
96+
97+
for (let i = 0; i < n; i++) {
98+
(await getDoc(doc(dbDefault, `firestore/cacheStressDoc_${i}`))).data().db.should.eql(
99+
'default',
100+
);
101+
(await getDoc(doc(dbSecond, `${COLLECTION}/cacheStressDoc_${i}`))).data().db.should.eql(
102+
'second',
103+
);
104+
}
105+
106+
for (let i = 0; i < n; i++) {
107+
await deleteDoc(doc(dbDefault, `firestore/cacheStressDoc_${i}`));
108+
await deleteDoc(doc(dbSecond, `${COLLECTION}/cacheStressDoc_${i}`));
109+
}
110+
});
111+
112+
it('terminate then reconnect both databases still isolates data (Android)', async function () {
113+
if (!Platform.android) {
114+
return;
115+
}
116+
const { getApp } = modular;
117+
const { getFirestore, doc, setDoc, getDoc, deleteDoc, terminate } = firestoreModular;
118+
119+
const app = getApp();
120+
let dbDefault = getFirestore(app, '(default)');
121+
let dbSecond = getFirestore(app, SECOND_DATABASE_ID);
122+
123+
await terminate(dbDefault);
124+
await terminate(dbSecond);
125+
126+
dbDefault = getFirestore(app, '(default)');
127+
dbSecond = getFirestore(app, SECOND_DATABASE_ID);
128+
129+
await setDoc(doc(dbDefault, 'firestore/afterTerminateProbe'), { tag: 'default' });
130+
await setDoc(doc(dbSecond, `${COLLECTION}/afterTerminateProbe`), { tag: 'second' });
131+
132+
(await getDoc(doc(dbDefault, 'firestore/afterTerminateProbe'))).data().tag.should.eql(
133+
'default',
134+
);
135+
(await getDoc(doc(dbSecond, `${COLLECTION}/afterTerminateProbe`))).data().tag.should.eql(
136+
'second',
137+
);
138+
139+
await deleteDoc(doc(dbDefault, 'firestore/afterTerminateProbe'));
140+
await deleteDoc(doc(dbSecond, `${COLLECTION}/afterTerminateProbe`));
141+
});
142+
});
143+
});
144+
24145
describe('firestore().collection().where()', function () {
25146
describe('v8 compatibility', function () {
26147
let firestore;

0 commit comments

Comments
 (0)