on-zero 0.6.3 → 0.6.5
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 +111 -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 +145 -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 +140 -14
- package/dist/cjs/helpers/recoverZeroClient.native.js +155 -22
- package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/cjs/helpers/recoverZeroClient.test.cjs +181 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js +209 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.native.js +1 -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/multiInstance.test.cjs +12 -0
- package/dist/cjs/multiInstance.test.native.js +21 -0
- package/dist/cjs/multiInstance.test.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 +112 -13
- package/dist/esm/createZeroClient.mjs.map +1 -1
- package/dist/esm/createZeroClient.native.js +146 -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 +140 -15
- package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.native.js +155 -23
- package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs +182 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js +210 -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/multiInstance.test.mjs +12 -0
- package/dist/esm/multiInstance.test.mjs.map +1 -1
- package/dist/esm/multiInstance.test.native.js +21 -0
- package/dist/esm/multiInstance.test.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 +188 -13
- package/src/helpers/recoverZeroClient.test.ts +204 -1
- package/src/helpers/recoverZeroClient.ts +263 -42
- package/src/index.ts +3 -0
- package/src/multi.ts +33 -0
- package/src/multiInstance.test.tsx +13 -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 +15 -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
|
@@ -24,11 +24,13 @@ var recoverZeroClient_exports = {};
|
|
|
24
24
|
__export(recoverZeroClient_exports, {
|
|
25
25
|
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
26
26
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
27
|
+
isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
|
|
27
28
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
28
29
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(recoverZeroClient_exports);
|
|
31
32
|
const RECOVER_GUARD_MS = 6e4;
|
|
33
|
+
const RELOAD_LATCH_TIMEOUT_MS = 15e3;
|
|
32
34
|
const LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
33
35
|
const SQLITE_ERROR_NAME = "SqliteError";
|
|
34
36
|
const SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
@@ -36,26 +38,69 @@ const STORE_CLOSED = "Store is closed";
|
|
|
36
38
|
const STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
37
39
|
const STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
38
40
|
let reloadScheduled = false;
|
|
41
|
+
let reloadInProgress = false;
|
|
42
|
+
let reloadLatchTimer;
|
|
39
43
|
const pendingDeletes = [];
|
|
40
|
-
|
|
44
|
+
const inMemoryGuard = /* @__PURE__ */new Map();
|
|
45
|
+
function defaultGuardStorage() {
|
|
41
46
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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);
|
|
49
68
|
return true;
|
|
50
69
|
}
|
|
51
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
|
+
}
|
|
52
97
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
53
98
|
if (typeof window === "undefined") return;
|
|
54
99
|
if (dropLocalState) {
|
|
55
|
-
pendingDeletes.push(Promise.resolve().then(deps.deleteLocalState)
|
|
100
|
+
pendingDeletes.push(() => Promise.resolve().then(deps.deleteLocalState));
|
|
56
101
|
}
|
|
57
102
|
if (reloadScheduled) return;
|
|
58
|
-
if (!recoveryGuardOpen(reasonKey)) {
|
|
103
|
+
if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
|
|
59
104
|
console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
|
|
60
105
|
deps.zeroEvents.emit({
|
|
61
106
|
type: "fatal",
|
|
@@ -64,13 +109,23 @@ function recover(deps, reasonKey, message, dropLocalState) {
|
|
|
64
109
|
return;
|
|
65
110
|
}
|
|
66
111
|
reloadScheduled = true;
|
|
112
|
+
armReloadLatchTimeout();
|
|
67
113
|
console.warn(`[on-zero] ${message} \u2014 recovering`);
|
|
68
114
|
deps.zeroEvents.emit({
|
|
69
115
|
type: "recovering",
|
|
70
116
|
reason: message
|
|
71
117
|
});
|
|
72
|
-
const
|
|
73
|
-
|
|
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
|
+
}
|
|
74
129
|
}
|
|
75
130
|
function makeZeroRecovery(deps) {
|
|
76
131
|
return {
|
|
@@ -103,6 +158,58 @@ function isBenignStoreClosedLog(text) {
|
|
|
103
158
|
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
104
159
|
return false;
|
|
105
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
|
+
}
|
|
106
213
|
function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
|
|
107
214
|
if (level !== "error") return void 0;
|
|
108
215
|
const text = args.map(logArgText).join(" ");
|
|
@@ -122,6 +229,13 @@ function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
|
|
|
122
229
|
dropLocalState: true
|
|
123
230
|
};
|
|
124
231
|
}
|
|
232
|
+
const desync = classifyMutationDesync(text);
|
|
233
|
+
if (desync) {
|
|
234
|
+
return {
|
|
235
|
+
...desync,
|
|
236
|
+
dropLocalState: true
|
|
237
|
+
};
|
|
238
|
+
}
|
|
125
239
|
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
126
240
|
const prevMs = lastStoreClosedAtMs;
|
|
127
241
|
lastStoreClosedAtMs = nowMs;
|
|
@@ -142,17 +256,29 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
142
256
|
log(level, context, ...args) {
|
|
143
257
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
144
258
|
const recovery = classifyZeroRecoveryLog(level, args);
|
|
145
|
-
if (recovery)
|
|
146
|
-
|
|
259
|
+
if (!recovery) return;
|
|
260
|
+
if (deps.benignLogFilter) {
|
|
261
|
+
const text = args.map(logArgText).join(" ");
|
|
262
|
+
if (deps.benignLogFilter(text)) return;
|
|
147
263
|
}
|
|
264
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
148
265
|
},
|
|
149
266
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
150
267
|
// rather than handing Zero a detached method reference.
|
|
151
268
|
flush: consumerFlush ? () => consumerFlush.call(consumerLogSink) : void 0
|
|
152
269
|
};
|
|
153
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
|
+
}
|
|
154
274
|
function resetRecoveryStateForTests() {
|
|
155
275
|
reloadScheduled = false;
|
|
276
|
+
reloadInProgress = false;
|
|
277
|
+
if (reloadLatchTimer) {
|
|
278
|
+
clearTimeout(reloadLatchTimer);
|
|
279
|
+
reloadLatchTimer = void 0;
|
|
280
|
+
}
|
|
156
281
|
pendingDeletes.length = 0;
|
|
157
282
|
lastStoreClosedAtMs = 0;
|
|
283
|
+
inMemoryGuard.clear();
|
|
158
284
|
}
|
|
@@ -26,6 +26,7 @@ var recoverZeroClient_exports = {};
|
|
|
26
26
|
__export(recoverZeroClient_exports, {
|
|
27
27
|
classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
|
|
28
28
|
composeRecoveryLogSink: () => composeRecoveryLogSink,
|
|
29
|
+
isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
|
|
29
30
|
makeZeroRecovery: () => makeZeroRecovery,
|
|
30
31
|
resetRecoveryStateForTests: () => resetRecoveryStateForTests
|
|
31
32
|
});
|
|
@@ -43,6 +44,7 @@ function _type_of(obj) {
|
|
|
43
44
|
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
44
45
|
}
|
|
45
46
|
var RECOVER_GUARD_MS = 6e4;
|
|
47
|
+
var RELOAD_LATCH_TIMEOUT_MS = 15e3;
|
|
46
48
|
var LOCAL_STORE_LOST = "Expected IndexedDB not found";
|
|
47
49
|
var SQLITE_ERROR_NAME = "SqliteError";
|
|
48
50
|
var SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
|
|
@@ -50,26 +52,83 @@ var STORE_CLOSED = "Store is closed";
|
|
|
50
52
|
var STORE_CLOSED_REPEAT_MIN_MS = 2e3;
|
|
51
53
|
var STORE_CLOSED_REPEAT_MAX_MS = 6e4;
|
|
52
54
|
var reloadScheduled = false;
|
|
55
|
+
var reloadInProgress = false;
|
|
56
|
+
var reloadLatchTimer;
|
|
53
57
|
var pendingDeletes = [];
|
|
54
|
-
|
|
58
|
+
var inMemoryGuard = /* @__PURE__ */new Map();
|
|
59
|
+
function defaultGuardStorage() {
|
|
55
60
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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);
|
|
63
83
|
return true;
|
|
64
84
|
}
|
|
65
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
|
+
}
|
|
66
123
|
function recover(deps, reasonKey, message, dropLocalState) {
|
|
67
124
|
if (typeof window === "undefined") return;
|
|
68
125
|
if (dropLocalState) {
|
|
69
|
-
pendingDeletes.push(
|
|
126
|
+
pendingDeletes.push(function () {
|
|
127
|
+
return Promise.resolve().then(deps.deleteLocalState);
|
|
128
|
+
});
|
|
70
129
|
}
|
|
71
130
|
if (reloadScheduled) return;
|
|
72
|
-
if (!recoveryGuardOpen(reasonKey)) {
|
|
131
|
+
if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
|
|
73
132
|
console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
|
|
74
133
|
deps.zeroEvents.emit({
|
|
75
134
|
type: "fatal",
|
|
@@ -78,22 +137,25 @@ function recover(deps, reasonKey, message, dropLocalState) {
|
|
|
78
137
|
return;
|
|
79
138
|
}
|
|
80
139
|
reloadScheduled = true;
|
|
140
|
+
armReloadLatchTimeout();
|
|
81
141
|
console.warn(`[on-zero] ${message} \u2014 recovering`);
|
|
82
142
|
deps.zeroEvents.emit({
|
|
83
143
|
type: "recovering",
|
|
84
144
|
reason: message
|
|
85
145
|
});
|
|
86
|
-
var
|
|
87
|
-
|
|
88
|
-
var _globalThis_location_reload, _globalThis_location;
|
|
89
|
-
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);
|
|
90
148
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
149
|
+
if (deps.scheduleReload) {
|
|
150
|
+
deps.scheduleReload({
|
|
151
|
+
reason: message,
|
|
152
|
+
reasonKey,
|
|
153
|
+
dropLocalState,
|
|
154
|
+
performReload: runReload
|
|
155
|
+
});
|
|
156
|
+
} else {
|
|
157
|
+
void runReload();
|
|
158
|
+
}
|
|
97
159
|
}
|
|
98
160
|
function makeZeroRecovery(deps) {
|
|
99
161
|
return {
|
|
@@ -132,6 +194,58 @@ function isBenignStoreClosedLog(text) {
|
|
|
132
194
|
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
|
|
133
195
|
return false;
|
|
134
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
|
+
}
|
|
135
249
|
function classifyZeroRecoveryLog(level, args) {
|
|
136
250
|
var nowMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
|
|
137
251
|
if (level !== "error") return void 0;
|
|
@@ -152,6 +266,13 @@ function classifyZeroRecoveryLog(level, args) {
|
|
|
152
266
|
dropLocalState: true
|
|
153
267
|
};
|
|
154
268
|
}
|
|
269
|
+
var desync = classifyMutationDesync(text);
|
|
270
|
+
if (desync) {
|
|
271
|
+
return {
|
|
272
|
+
...desync,
|
|
273
|
+
dropLocalState: true
|
|
274
|
+
};
|
|
275
|
+
}
|
|
155
276
|
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
156
277
|
var prevMs = lastStoreClosedAtMs;
|
|
157
278
|
lastStoreClosedAtMs = nowMs;
|
|
@@ -175,9 +296,12 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
175
296
|
}
|
|
176
297
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
|
|
177
298
|
var recovery = classifyZeroRecoveryLog(level, args);
|
|
178
|
-
if (recovery)
|
|
179
|
-
|
|
299
|
+
if (!recovery) return;
|
|
300
|
+
if (deps.benignLogFilter) {
|
|
301
|
+
var text = args.map(logArgText).join(" ");
|
|
302
|
+
if (deps.benignLogFilter(text)) return;
|
|
180
303
|
}
|
|
304
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
|
|
181
305
|
},
|
|
182
306
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
183
307
|
// rather than handing Zero a detached method reference.
|
|
@@ -186,9 +310,18 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
|
|
|
186
310
|
} : void 0
|
|
187
311
|
};
|
|
188
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
|
+
}
|
|
189
316
|
function resetRecoveryStateForTests() {
|
|
190
317
|
reloadScheduled = false;
|
|
318
|
+
reloadInProgress = false;
|
|
319
|
+
if (reloadLatchTimer) {
|
|
320
|
+
clearTimeout(reloadLatchTimer);
|
|
321
|
+
reloadLatchTimer = void 0;
|
|
322
|
+
}
|
|
191
323
|
pendingDeletes.length = 0;
|
|
192
324
|
lastStoreClosedAtMs = 0;
|
|
325
|
+
inMemoryGuard.clear();
|
|
193
326
|
}
|
|
194
327
|
//# sourceMappingURL=recoverZeroClient.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","classifyZeroRecoveryLog","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","module","exports","_instanceof","left","right","Symbol","hasInstance","_type_of","obj","constructor","RECOVER_GUARD_MS","LOCAL_STORE_LOST","SQLITE_ERROR_NAME","SQLITE_STATEMENT_FINALIZED","STORE_CLOSED","STORE_CLOSED_REPEAT_MIN_MS","STORE_CLOSED_REPEAT_MAX_MS","reloadScheduled","
|
|
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":[]}
|