on-zero 0.6.2 → 0.6.4
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.
- package/dist/cjs/createZeroClient.cjs +91 -12
- package/dist/cjs/createZeroClient.connection.test.cjs +163 -0
- package/dist/cjs/createZeroClient.connection.test.native.js +242 -0
- package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -0
- package/dist/cjs/createZeroClient.native.js +99 -12
- package/dist/cjs/createZeroClient.native.js.map +1 -1
- package/dist/cjs/createZeroClient.recovery.test.cjs +52 -0
- package/dist/cjs/createZeroClient.recovery.test.native.js +52 -0
- package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
- package/dist/cjs/helpers/recoverZeroClient.cjs +197 -14
- package/dist/cjs/helpers/recoverZeroClient.native.js +220 -24
- package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/cjs/helpers/recoverZeroClient.test.cjs +241 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js +269 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/multi.cjs +13 -0
- package/dist/cjs/multi.native.js +35 -0
- package/dist/cjs/multi.native.js.map +1 -1
- package/dist/cjs/multiPartition.test.cjs +42 -0
- package/dist/cjs/multiPartition.test.native.js +51 -0
- package/dist/cjs/multiPartition.test.native.js.map +1 -0
- package/dist/esm/createZeroClient.connection.test.mjs +164 -0
- package/dist/esm/createZeroClient.connection.test.mjs.map +1 -0
- package/dist/esm/createZeroClient.connection.test.native.js +240 -0
- package/dist/esm/createZeroClient.connection.test.native.js.map +1 -0
- package/dist/esm/createZeroClient.mjs +92 -13
- package/dist/esm/createZeroClient.mjs.map +1 -1
- package/dist/esm/createZeroClient.native.js +100 -13
- package/dist/esm/createZeroClient.native.js.map +1 -1
- package/dist/esm/createZeroClient.recovery.test.mjs +52 -0
- package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
- package/dist/esm/createZeroClient.recovery.test.native.js +52 -0
- package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.mjs +196 -15
- package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.native.js +219 -25
- package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs +242 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js +270 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -2
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/multi.mjs +13 -1
- package/dist/esm/multi.mjs.map +1 -1
- package/dist/esm/multi.native.js +35 -1
- package/dist/esm/multi.native.js.map +1 -1
- package/dist/esm/multiPartition.test.mjs +43 -0
- package/dist/esm/multiPartition.test.mjs.map +1 -0
- package/dist/esm/multiPartition.test.native.js +49 -0
- package/dist/esm/multiPartition.test.native.js.map +1 -0
- package/lint/ssr-guards.js +164 -0
- package/package.json +2 -2
- package/readme.md +126 -0
- package/src/createZeroClient.connection.test.tsx +162 -0
- package/src/createZeroClient.recovery.test.tsx +68 -0
- package/src/createZeroClient.tsx +159 -13
- package/src/helpers/recoverZeroClient.test.ts +270 -1
- package/src/helpers/recoverZeroClient.ts +347 -50
- package/src/index.ts +6 -0
- package/src/multi.ts +33 -0
- package/src/multiPartition.test.ts +38 -0
- package/types/createZeroClient.connection.test.d.ts +5 -0
- package/types/createZeroClient.connection.test.d.ts.map +1 -0
- package/types/createZeroClient.d.ts +17 -0
- package/types/createZeroClient.d.ts.map +1 -1
- package/types/createZeroServer.d.ts +4 -4
- package/types/helpers/recoverZeroClient.d.ts +23 -1
- package/types/helpers/recoverZeroClient.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/multi.d.ts +1 -0
- package/types/multi.d.ts.map +1 -1
- package/types/multiPartition.test.d.ts +2 -0
- package/types/multiPartition.test.d.ts.map +1 -0
|
@@ -22,31 +22,85 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
22
22
|
}), mod);
|
|
23
23
|
var recoverZeroClient_exports = {};
|
|
24
24
|
__export(recoverZeroClient_exports, {
|
|
25
|
+
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
25
26
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
27
|
+
isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
|
|
26
28
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
27
29
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(recoverZeroClient_exports);
|
|
30
32
|
const RECOVER_GUARD_MS = 6e4;
|
|
33
|
+
const RELOAD_LATCH_TIMEOUT_MS = 15e3;
|
|
31
34
|
const LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
35
|
+
const SQLITE_ERROR_NAME = "SqliteError";
|
|
36
|
+
const SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
37
|
+
const STORE_CLOSED = "Store is closed";
|
|
38
|
+
const STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
39
|
+
const STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
32
40
|
let reloadScheduled = false;
|
|
41
|
+
let reloadInProgress = false;
|
|
42
|
+
let reloadLatchTimer;
|
|
33
43
|
const pendingDeletes = [];
|
|
34
|
-
|
|
44
|
+
const inMemoryGuard = /* @__PURE__ */new Map();
|
|
45
|
+
function defaultGuardStorage() {
|
|
35
46
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
47
|
+
if (typeof window === "undefined" || !window.sessionStorage) return void 0;
|
|
48
|
+
return window.sessionStorage;
|
|
49
|
+
} catch {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function recoveryGuardOpen(reasonKey, guardStorage) {
|
|
54
|
+
const key = `on-zero-recover-${reasonKey}`;
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const memLast = inMemoryGuard.get(key) ?? 0;
|
|
57
|
+
if (memLast > 0 && now - memLast < RECOVER_GUARD_MS) return false;
|
|
58
|
+
const storage = guardStorage ?? defaultGuardStorage();
|
|
59
|
+
if (storage) {
|
|
60
|
+
try {
|
|
61
|
+
const rawLast = storage.getItem(key);
|
|
62
|
+
const last = rawLast ? Number(rawLast) : 0;
|
|
63
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
|
|
64
|
+
storage.setItem(key, String(now));
|
|
65
|
+
} catch {}
|
|
66
|
+
}
|
|
67
|
+
inMemoryGuard.set(key, now);
|
|
41
68
|
return true;
|
|
42
69
|
}
|
|
70
|
+
let lastStoreClosedAtMs = 0;
|
|
71
|
+
function armReloadLatchTimeout() {
|
|
72
|
+
if (typeof setTimeout !== "function") return;
|
|
73
|
+
if (reloadLatchTimer) clearTimeout(reloadLatchTimer);
|
|
74
|
+
reloadLatchTimer = setTimeout(() => {
|
|
75
|
+
reloadLatchTimer = void 0;
|
|
76
|
+
reloadScheduled = false;
|
|
77
|
+
}, RELOAD_LATCH_TIMEOUT_MS);
|
|
78
|
+
if (reloadLatchTimer && typeof reloadLatchTimer === "object" && "unref" in reloadLatchTimer) {
|
|
79
|
+
reloadLatchTimer.unref();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function disarmReloadLatchTimeout() {
|
|
83
|
+
if (reloadLatchTimer) {
|
|
84
|
+
clearTimeout(reloadLatchTimer);
|
|
85
|
+
reloadLatchTimer = void 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function performReload(deps) {
|
|
89
|
+
if (reloadInProgress) return Promise.resolve();
|
|
90
|
+
reloadInProgress = true;
|
|
91
|
+
disarmReloadLatchTimeout();
|
|
92
|
+
const doReload = deps.reload ?? (() => globalThis.location?.reload?.());
|
|
93
|
+
return Promise.resolve().then(() => Promise.allSettled(pendingDeletes.splice(0).map(run => run()))).then(() => deps.beforeReload?.()).catch(() => {}).then(() => {
|
|
94
|
+
doReload();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
43
97
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
44
98
|
if (typeof window === "undefined") return;
|
|
45
99
|
if (dropLocalState) {
|
|
46
|
-
pendingDeletes.push(Promise.resolve().then(deps.deleteLocalState)
|
|
100
|
+
pendingDeletes.push(() => Promise.resolve().then(deps.deleteLocalState));
|
|
47
101
|
}
|
|
48
102
|
if (reloadScheduled) return;
|
|
49
|
-
if (!recoveryGuardOpen(reasonKey)) {
|
|
103
|
+
if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
|
|
50
104
|
console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
|
|
51
105
|
deps.zeroEvents.emit({
|
|
52
106
|
type: "fatal",
|
|
@@ -55,13 +109,23 @@ function recover(deps, reasonKey, message, dropLocalState) {
|
|
|
55
109
|
return;
|
|
56
110
|
}
|
|
57
111
|
reloadScheduled = true;
|
|
112
|
+
armReloadLatchTimeout();
|
|
58
113
|
console.warn(`[on-zero] ${message} \u2014 recovering`);
|
|
59
114
|
deps.zeroEvents.emit({
|
|
60
115
|
type: "recovering",
|
|
61
116
|
reason: message
|
|
62
117
|
});
|
|
63
|
-
const
|
|
64
|
-
|
|
118
|
+
const runReload = () => performReload(deps);
|
|
119
|
+
if (deps.scheduleReload) {
|
|
120
|
+
deps.scheduleReload({
|
|
121
|
+
reason: message,
|
|
122
|
+
reasonKey,
|
|
123
|
+
dropLocalState,
|
|
124
|
+
performReload: runReload
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
void runReload();
|
|
128
|
+
}
|
|
65
129
|
}
|
|
66
130
|
function makeZeroRecovery(deps) {
|
|
67
131
|
return {
|
|
@@ -79,23 +143,142 @@ function logToConsole(level, context, ...args) {
|
|
|
79
143
|
const method = level === "debug" ? "debug" : level;
|
|
80
144
|
console[method](...(prefix ? [prefix] : []), ...args);
|
|
81
145
|
}
|
|
146
|
+
function logArgText(arg) {
|
|
147
|
+
if (typeof arg === "string") return arg;
|
|
148
|
+
if (arg instanceof Error) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
|
|
149
|
+
if (arg && typeof arg === "object") {
|
|
150
|
+
const message = "message" in arg ? arg.message : void 0;
|
|
151
|
+
const name = "name" in arg ? arg.name : void 0;
|
|
152
|
+
if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
|
|
153
|
+
}
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
function isBenignStoreClosedLog(text) {
|
|
157
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
|
|
158
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
function classifyMutationDesync(text) {
|
|
162
|
+
if (text.includes("sent mutation ID") && text.includes("but expected")) {
|
|
163
|
+
return {
|
|
164
|
+
reason: "mutation-desync",
|
|
165
|
+
reasonKey: "mutation-desync",
|
|
166
|
+
message: "mutation id desync"
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (text.includes("oooMutation") || text.includes("Server reported an out-of-order mutation")) {
|
|
170
|
+
return {
|
|
171
|
+
reason: "mutation-desync",
|
|
172
|
+
reasonKey: "mutation-desync",
|
|
173
|
+
message: "out-of-order mutation"
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (text.includes("already processed")) {
|
|
177
|
+
return {
|
|
178
|
+
reason: "mutation-desync",
|
|
179
|
+
reasonKey: "mutation-desync",
|
|
180
|
+
message: "mutation already processed"
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (text.includes("InvalidConnectionRequestLastMutationID")) {
|
|
184
|
+
return {
|
|
185
|
+
reason: "mutation-desync",
|
|
186
|
+
reasonKey: "mutation-desync",
|
|
187
|
+
message: "invalid connection last mutation id"
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (text.includes("InvalidConnectionRequestBaseCookie")) {
|
|
191
|
+
return {
|
|
192
|
+
reason: "connection-cookie-invalid",
|
|
193
|
+
reasonKey: "connection-cookie-invalid",
|
|
194
|
+
message: "invalid connection base cookie"
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (text.includes("ClientNotFound") || text.includes("Client not found")) {
|
|
198
|
+
return {
|
|
199
|
+
reason: "client-not-found",
|
|
200
|
+
reasonKey: "client-not-found",
|
|
201
|
+
message: "client not found"
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (text.includes("connection userID mismatch")) {
|
|
205
|
+
return {
|
|
206
|
+
reason: "connection-userid-mismatch",
|
|
207
|
+
reasonKey: "connection-userid-mismatch",
|
|
208
|
+
message: "connection user id mismatch"
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
|
|
214
|
+
if (level !== "error") return void 0;
|
|
215
|
+
const text = args.map(logArgText).join(" ");
|
|
216
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
217
|
+
return {
|
|
218
|
+
reason: "indexeddb-not-found",
|
|
219
|
+
reasonKey: "local-store",
|
|
220
|
+
message: "local store lost",
|
|
221
|
+
dropLocalState: true
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
225
|
+
return {
|
|
226
|
+
reason: "sqlite-statement-finalized",
|
|
227
|
+
reasonKey: "sqlite-statement-finalized",
|
|
228
|
+
message: "sqlite statement finalized",
|
|
229
|
+
dropLocalState: true
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const desync = classifyMutationDesync(text);
|
|
233
|
+
if (desync) {
|
|
234
|
+
return {
|
|
235
|
+
...desync,
|
|
236
|
+
dropLocalState: true
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
240
|
+
const prevMs = lastStoreClosedAtMs;
|
|
241
|
+
lastStoreClosedAtMs = nowMs;
|
|
242
|
+
if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
|
|
243
|
+
return {
|
|
244
|
+
reason: "store-closed-repeat",
|
|
245
|
+
reasonKey: "store-closed-repeat",
|
|
246
|
+
message: "local store closed repeatedly",
|
|
247
|
+
dropLocalState: true
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return void 0;
|
|
252
|
+
}
|
|
82
253
|
function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
83
254
|
const consumerFlush = consumerLogSink?.flush;
|
|
84
255
|
return {
|
|
85
256
|
log(level, context, ...args) {
|
|
86
257
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
258
|
+
const recovery = classifyZeroRecoveryLog(level, args);
|
|
259
|
+
if (!recovery) return;
|
|
260
|
+
if (deps.benignLogFilter) {
|
|
261
|
+
const text = args.map(logArgText).join(" ");
|
|
262
|
+
if (deps.benignLogFilter(text)) return;
|
|
91
263
|
}
|
|
264
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
92
265
|
},
|
|
93
266
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
94
267
|
// rather than handing Zero a detached method reference.
|
|
95
268
|
flush: consumerFlush ? () => consumerFlush.call(consumerLogSink) : void 0
|
|
96
269
|
};
|
|
97
270
|
}
|
|
271
|
+
function isRecoverableZeroStalePokeMessage(message) {
|
|
272
|
+
return message.includes("Server returned unexpected base cookie during sync") || message.includes("Received cookie") && message.includes("is < than last snapshot cookie") && message.includes("ignoring client view");
|
|
273
|
+
}
|
|
98
274
|
function resetRecoveryStateForTests() {
|
|
99
275
|
reloadScheduled = false;
|
|
276
|
+
reloadInProgress = false;
|
|
277
|
+
if (reloadLatchTimer) {
|
|
278
|
+
clearTimeout(reloadLatchTimer);
|
|
279
|
+
reloadLatchTimer = void 0;
|
|
280
|
+
}
|
|
100
281
|
pendingDeletes.length = 0;
|
|
282
|
+
lastStoreClosedAtMs = 0;
|
|
283
|
+
inMemoryGuard.clear();
|
|
101
284
|
}
|
|
@@ -24,36 +24,111 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
24
24
|
}), mod);
|
|
25
25
|
var recoverZeroClient_exports = {};
|
|
26
26
|
__export(recoverZeroClient_exports, {
|
|
27
|
+
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
27
28
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
29
|
+
isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
|
|
28
30
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
29
31
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
30
32
|
});
|
|
31
33
|
module.exports = __toCommonJS(recoverZeroClient_exports);
|
|
34
|
+
function _instanceof(left, right) {
|
|
35
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
36
|
+
return !!right[Symbol.hasInstance](left);
|
|
37
|
+
} else {
|
|
38
|
+
return left instanceof right;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
32
41
|
function _type_of(obj) {
|
|
33
42
|
"@swc/helpers - typeof";
|
|
34
43
|
|
|
35
44
|
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
36
45
|
}
|
|
37
46
|
var RECOVER_GUARD_MS = 6e4;
|
|
47
|
+
var RELOAD_LATCH_TIMEOUT_MS = 15e3;
|
|
38
48
|
var LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
49
|
+
var SQLITE_ERROR_NAME = "SqliteError";
|
|
50
|
+
var SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
51
|
+
var STORE_CLOSED = "Store is closed";
|
|
52
|
+
var STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
53
|
+
var STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
39
54
|
var reloadScheduled = false;
|
|
55
|
+
var reloadInProgress = false;
|
|
56
|
+
var reloadLatchTimer;
|
|
40
57
|
var pendingDeletes = [];
|
|
41
|
-
|
|
58
|
+
var inMemoryGuard = /* @__PURE__ */new Map();
|
|
59
|
+
function defaultGuardStorage() {
|
|
42
60
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
61
|
+
if (typeof window === "undefined" || !window.sessionStorage) return void 0;
|
|
62
|
+
return window.sessionStorage;
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function recoveryGuardOpen(reasonKey, guardStorage) {
|
|
68
|
+
var key = `on-zero-recover-${reasonKey}`;
|
|
69
|
+
var now = Date.now();
|
|
70
|
+
var _inMemoryGuard_get;
|
|
71
|
+
var memLast = (_inMemoryGuard_get = inMemoryGuard.get(key)) !== null && _inMemoryGuard_get !== void 0 ? _inMemoryGuard_get : 0;
|
|
72
|
+
if (memLast > 0 && now - memLast < RECOVER_GUARD_MS) return false;
|
|
73
|
+
var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
|
|
74
|
+
if (storage) {
|
|
75
|
+
try {
|
|
76
|
+
var rawLast = storage.getItem(key);
|
|
77
|
+
var last = rawLast ? Number(rawLast) : 0;
|
|
78
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
|
|
79
|
+
storage.setItem(key, String(now));
|
|
80
|
+
} catch (e) {}
|
|
81
|
+
}
|
|
82
|
+
inMemoryGuard.set(key, now);
|
|
48
83
|
return true;
|
|
49
84
|
}
|
|
85
|
+
var lastStoreClosedAtMs = 0;
|
|
86
|
+
function armReloadLatchTimeout() {
|
|
87
|
+
if (typeof setTimeout !== "function") return;
|
|
88
|
+
if (reloadLatchTimer) clearTimeout(reloadLatchTimer);
|
|
89
|
+
reloadLatchTimer = setTimeout(function () {
|
|
90
|
+
reloadLatchTimer = void 0;
|
|
91
|
+
reloadScheduled = false;
|
|
92
|
+
}, RELOAD_LATCH_TIMEOUT_MS);
|
|
93
|
+
if (reloadLatchTimer && (typeof reloadLatchTimer === "undefined" ? "undefined" : _type_of(reloadLatchTimer)) === "object" && "unref" in reloadLatchTimer) {
|
|
94
|
+
reloadLatchTimer.unref();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function disarmReloadLatchTimeout() {
|
|
98
|
+
if (reloadLatchTimer) {
|
|
99
|
+
clearTimeout(reloadLatchTimer);
|
|
100
|
+
reloadLatchTimer = void 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function performReload(deps) {
|
|
104
|
+
if (reloadInProgress) return Promise.resolve();
|
|
105
|
+
reloadInProgress = true;
|
|
106
|
+
disarmReloadLatchTimeout();
|
|
107
|
+
var _deps_reload;
|
|
108
|
+
var doReload = (_deps_reload = deps.reload) !== null && _deps_reload !== void 0 ? _deps_reload : function () {
|
|
109
|
+
var _globalThis_location_reload, _globalThis_location;
|
|
110
|
+
return (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : (_globalThis_location_reload = _globalThis_location.reload) === null || _globalThis_location_reload === void 0 ? void 0 : _globalThis_location_reload.call(_globalThis_location);
|
|
111
|
+
};
|
|
112
|
+
return Promise.resolve().then(function () {
|
|
113
|
+
return Promise.allSettled(pendingDeletes.splice(0).map(function (run) {
|
|
114
|
+
return run();
|
|
115
|
+
}));
|
|
116
|
+
}).then(function () {
|
|
117
|
+
var _deps_beforeReload;
|
|
118
|
+
return (_deps_beforeReload = deps.beforeReload) === null || _deps_beforeReload === void 0 ? void 0 : _deps_beforeReload.call(deps);
|
|
119
|
+
}).catch(function () {}).then(function () {
|
|
120
|
+
doReload();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
50
123
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
51
124
|
if (typeof window === "undefined") return;
|
|
52
125
|
if (dropLocalState) {
|
|
53
|
-
pendingDeletes.push(
|
|
126
|
+
pendingDeletes.push(function () {
|
|
127
|
+
return Promise.resolve().then(deps.deleteLocalState);
|
|
128
|
+
});
|
|
54
129
|
}
|
|
55
130
|
if (reloadScheduled) return;
|
|
56
|
-
if (!recoveryGuardOpen(reasonKey)) {
|
|
131
|
+
if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
|
|
57
132
|
console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
|
|
58
133
|
deps.zeroEvents.emit({
|
|
59
134
|
type: "fatal",
|
|
@@ -62,22 +137,25 @@ function recover(deps, reasonKey, message, dropLocalState) {
|
|
|
62
137
|
return;
|
|
63
138
|
}
|
|
64
139
|
reloadScheduled = true;
|
|
140
|
+
armReloadLatchTimeout();
|
|
65
141
|
console.warn(`[on-zero] ${message} \u2014 recovering`);
|
|
66
142
|
deps.zeroEvents.emit({
|
|
67
143
|
type: "recovering",
|
|
68
144
|
reason: message
|
|
69
145
|
});
|
|
70
|
-
var
|
|
71
|
-
|
|
72
|
-
var _globalThis_location_reload, _globalThis_location;
|
|
73
|
-
return (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : (_globalThis_location_reload = _globalThis_location.reload) === null || _globalThis_location_reload === void 0 ? void 0 : _globalThis_location_reload.call(_globalThis_location);
|
|
146
|
+
var runReload = function () {
|
|
147
|
+
return performReload(deps);
|
|
74
148
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
149
|
+
if (deps.scheduleReload) {
|
|
150
|
+
deps.scheduleReload({
|
|
151
|
+
reason: message,
|
|
152
|
+
reasonKey,
|
|
153
|
+
dropLocalState,
|
|
154
|
+
performReload: runReload
|
|
155
|
+
});
|
|
156
|
+
} else {
|
|
157
|
+
void runReload();
|
|
158
|
+
}
|
|
81
159
|
}
|
|
82
160
|
function makeZeroRecovery(deps) {
|
|
83
161
|
return {
|
|
@@ -101,6 +179,114 @@ function logToConsole(level, context) {
|
|
|
101
179
|
var method = level === "debug" ? "debug" : level;
|
|
102
180
|
console[method](...(prefix ? [prefix] : []), ...args);
|
|
103
181
|
}
|
|
182
|
+
function logArgText(arg) {
|
|
183
|
+
if (typeof arg === "string") return arg;
|
|
184
|
+
if (_instanceof(arg, Error)) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
|
|
185
|
+
if (arg && (typeof arg === "undefined" ? "undefined" : _type_of(arg)) === "object") {
|
|
186
|
+
var message = "message" in arg ? arg.message : void 0;
|
|
187
|
+
var name = "name" in arg ? arg.name : void 0;
|
|
188
|
+
if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
|
|
189
|
+
}
|
|
190
|
+
return "";
|
|
191
|
+
}
|
|
192
|
+
function isBenignStoreClosedLog(text) {
|
|
193
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
|
|
194
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
function classifyMutationDesync(text) {
|
|
198
|
+
if (text.includes("sent mutation ID") && text.includes("but expected")) {
|
|
199
|
+
return {
|
|
200
|
+
reason: "mutation-desync",
|
|
201
|
+
reasonKey: "mutation-desync",
|
|
202
|
+
message: "mutation id desync"
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (text.includes("oooMutation") || text.includes("Server reported an out-of-order mutation")) {
|
|
206
|
+
return {
|
|
207
|
+
reason: "mutation-desync",
|
|
208
|
+
reasonKey: "mutation-desync",
|
|
209
|
+
message: "out-of-order mutation"
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (text.includes("already processed")) {
|
|
213
|
+
return {
|
|
214
|
+
reason: "mutation-desync",
|
|
215
|
+
reasonKey: "mutation-desync",
|
|
216
|
+
message: "mutation already processed"
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (text.includes("InvalidConnectionRequestLastMutationID")) {
|
|
220
|
+
return {
|
|
221
|
+
reason: "mutation-desync",
|
|
222
|
+
reasonKey: "mutation-desync",
|
|
223
|
+
message: "invalid connection last mutation id"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (text.includes("InvalidConnectionRequestBaseCookie")) {
|
|
227
|
+
return {
|
|
228
|
+
reason: "connection-cookie-invalid",
|
|
229
|
+
reasonKey: "connection-cookie-invalid",
|
|
230
|
+
message: "invalid connection base cookie"
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (text.includes("ClientNotFound") || text.includes("Client not found")) {
|
|
234
|
+
return {
|
|
235
|
+
reason: "client-not-found",
|
|
236
|
+
reasonKey: "client-not-found",
|
|
237
|
+
message: "client not found"
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
if (text.includes("connection userID mismatch")) {
|
|
241
|
+
return {
|
|
242
|
+
reason: "connection-userid-mismatch",
|
|
243
|
+
reasonKey: "connection-userid-mismatch",
|
|
244
|
+
message: "connection user id mismatch"
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return void 0;
|
|
248
|
+
}
|
|
249
|
+
function classifyZeroRecoveryLog(level, args) {
|
|
250
|
+
var nowMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
|
|
251
|
+
if (level !== "error") return void 0;
|
|
252
|
+
var text = args.map(logArgText).join(" ");
|
|
253
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
254
|
+
return {
|
|
255
|
+
reason: "indexeddb-not-found",
|
|
256
|
+
reasonKey: "local-store",
|
|
257
|
+
message: "local store lost",
|
|
258
|
+
dropLocalState: true
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
262
|
+
return {
|
|
263
|
+
reason: "sqlite-statement-finalized",
|
|
264
|
+
reasonKey: "sqlite-statement-finalized",
|
|
265
|
+
message: "sqlite statement finalized",
|
|
266
|
+
dropLocalState: true
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
var desync = classifyMutationDesync(text);
|
|
270
|
+
if (desync) {
|
|
271
|
+
return {
|
|
272
|
+
...desync,
|
|
273
|
+
dropLocalState: true
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
277
|
+
var prevMs = lastStoreClosedAtMs;
|
|
278
|
+
lastStoreClosedAtMs = nowMs;
|
|
279
|
+
if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
|
|
280
|
+
return {
|
|
281
|
+
reason: "store-closed-repeat",
|
|
282
|
+
reasonKey: "store-closed-repeat",
|
|
283
|
+
message: "local store closed repeatedly",
|
|
284
|
+
dropLocalState: true
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return void 0;
|
|
289
|
+
}
|
|
104
290
|
function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
105
291
|
var consumerFlush = consumerLogSink === null || consumerLogSink === void 0 ? void 0 : consumerLogSink.flush;
|
|
106
292
|
return {
|
|
@@ -109,13 +295,13 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
109
295
|
args[_key - 2] = arguments[_key];
|
|
110
296
|
}
|
|
111
297
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
recover(deps, "local-store", "local store lost", true);
|
|
298
|
+
var recovery = classifyZeroRecoveryLog(level, args);
|
|
299
|
+
if (!recovery) return;
|
|
300
|
+
if (deps.benignLogFilter) {
|
|
301
|
+
var text = args.map(logArgText).join(" ");
|
|
302
|
+
if (deps.benignLogFilter(text)) return;
|
|
118
303
|
}
|
|
304
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
119
305
|
},
|
|
120
306
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
121
307
|
// rather than handing Zero a detached method reference.
|
|
@@ -124,8 +310,18 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
124
310
|
} : void 0
|
|
125
311
|
};
|
|
126
312
|
}
|
|
313
|
+
function isRecoverableZeroStalePokeMessage(message) {
|
|
314
|
+
return message.includes("Server returned unexpected base cookie during sync") || message.includes("Received cookie") && message.includes("is < than last snapshot cookie") && message.includes("ignoring client view");
|
|
315
|
+
}
|
|
127
316
|
function resetRecoveryStateForTests() {
|
|
128
317
|
reloadScheduled = false;
|
|
318
|
+
reloadInProgress = false;
|
|
319
|
+
if (reloadLatchTimer) {
|
|
320
|
+
clearTimeout(reloadLatchTimer);
|
|
321
|
+
reloadLatchTimer = void 0;
|
|
322
|
+
}
|
|
129
323
|
pendingDeletes.length = 0;
|
|
324
|
+
lastStoreClosedAtMs = 0;
|
|
325
|
+
inMemoryGuard.clear();
|
|
130
326
|
}
|
|
131
327
|
//# sourceMappingURL=recoverZeroClient.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","module","exports","
|
|
1
|
+
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","classifyZeroRecoveryLog","composeRecoveryLogSink","isRecoverableZeroStalePokeMessage","makeZeroRecovery","resetRecoveryStateForTests","module","exports","_instanceof","left","right","Symbol","hasInstance","_type_of","obj","constructor","RECOVER_GUARD_MS","RELOAD_LATCH_TIMEOUT_MS","LOCAL_STORE_LOST","SQLITE_ERROR_NAME","SQLITE_STATEMENT_FINALIZED","STORE_CLOSED","STORE_CLOSED_REPEAT_MIN_MS","STORE_CLOSED_REPEAT_MAX_MS","reloadScheduled","reloadInProgress","reloadLatchTimer","pendingDeletes","inMemoryGuard","Map","defaultGuardStorage","window","sessionStorage","e","recoveryGuardOpen","reasonKey","guardStorage","key","now","Date","_inMemoryGuard_get","memLast","get","storage","rawLast","getItem","last","Number","setItem","String","set","lastStoreClosedAtMs","armReloadLatchTimeout","setTimeout","clearTimeout","unref","disarmReloadLatchTimeout","performReload","deps","Promise","resolve","_deps_reload","doReload","reload","_globalThis_location_reload","_globalThis_location","globalThis","location","call","then","allSettled","splice","map","run","_deps_beforeReload","beforeReload","catch","recover","message","dropLocalState","push","deleteLocalState","console","error","zeroEvents","emit","type","reason","warn","runReload","scheduleReload","onUpdateNeeded","onClientStateNotFound","logToConsole","level","context","_len","arguments","length","args","Array","_key","prefix","Object","entries","param","join","method","logArgText","arg","Error","name","stack","isBenignStoreClosedLog","text","test","classifyMutationDesync","includes","nowMs","desync","prevMs"],"sources":["../../../src/helpers/recoverZeroClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|