react-native-onyx 3.0.86 → 3.0.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -69,6 +69,10 @@ function getBudgetedHealErrorLabel(error) {
|
|
|
69
69
|
return 'connection lost';
|
|
70
70
|
return 'unknown';
|
|
71
71
|
}
|
|
72
|
+
/** Union of all error types indicating a stale/dead IDB connection. Used by the visibilitychange probe. */
|
|
73
|
+
function isStaleConnectionError(error) {
|
|
74
|
+
return isInvalidStateError(error) || isBackingStoreError(error) || isConnectionLostError(error);
|
|
75
|
+
}
|
|
72
76
|
// This is a copy of the createStore function from idb-keyval, we need a custom implementation
|
|
73
77
|
// because we need to create the database manually in order to ensure that the store exists before we use it.
|
|
74
78
|
// If the store does not exist, idb-keyval will throw an error
|
|
@@ -146,6 +150,52 @@ function createStore(dbName, storeName) {
|
|
|
146
150
|
healAttemptsRemaining = HEAL_ATTEMPTS_MAX;
|
|
147
151
|
return result;
|
|
148
152
|
}
|
|
153
|
+
// Proactive IDB health check when tab returns to foreground.
|
|
154
|
+
// Safari kills IDB connections for backgrounded tabs. By probing as soon as
|
|
155
|
+
// the tab becomes visible, we drop the stale dbp early so the first real
|
|
156
|
+
// operation opens a fresh connection instead of failing.
|
|
157
|
+
document.addEventListener('visibilitychange', () => {
|
|
158
|
+
if (document.visibilityState !== 'visible' || !dbp) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
Logger.logInfo('IDB visibilitychange probe: tab became visible, checking connection health', { dbName, storeName });
|
|
162
|
+
const probePromise = dbp;
|
|
163
|
+
const dropCacheIfStale = (error) => {
|
|
164
|
+
if (dbp !== probePromise || !isStaleConnectionError(error)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
Logger.logAlert('IDB visibilitychange probe: stale connection detected, dropping cached connection', {
|
|
168
|
+
dbName,
|
|
169
|
+
storeName,
|
|
170
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
171
|
+
});
|
|
172
|
+
dbp = undefined;
|
|
173
|
+
};
|
|
174
|
+
probePromise
|
|
175
|
+
.then((db) => {
|
|
176
|
+
if (dbp !== probePromise) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const tx = db.transaction(storeName, 'readonly');
|
|
181
|
+
const probeStore = tx.objectStore(storeName);
|
|
182
|
+
const req = probeStore.count();
|
|
183
|
+
req.onsuccess = () => {
|
|
184
|
+
Logger.logInfo('IDB visibilitychange probe: connection is healthy', { dbName, storeName });
|
|
185
|
+
};
|
|
186
|
+
req.onerror = () => {
|
|
187
|
+
dropCacheIfStale(req.error);
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
dropCacheIfStale(error);
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
.catch(() => {
|
|
195
|
+
// The cached open promise rejected; cacheOpenPromise already cleared dbp on its own
|
|
196
|
+
// branch. Swallow here so the probe's separate branch doesn't surface an unhandled rejection.
|
|
197
|
+
});
|
|
198
|
+
});
|
|
149
199
|
// Handles three recoverable error classes:
|
|
150
200
|
// 1. InvalidStateError — connection closed between getDB() resolving and db.transaction().
|
|
151
201
|
// Retry once with a fresh connection. No budget limit (transient, always worth one reopen).
|