Offline retry queue for userscript writes #5
@@ -440,6 +440,31 @@
|
|||||||
saveQueue(queue);
|
saveQueue(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let draining = false;
|
||||||
|
|
||||||
|
// Replays everything owed. Cheap in the normal case — it returns on the first
|
||||||
|
// line when the queue is empty, which is why it can hang off navigation. A
|
||||||
|
// 401 stops the whole pass: the token is wrong, so the next entry would fail
|
||||||
|
// the same way, and the queue is left intact so fixing the token fixes it.
|
||||||
|
async function drain() {
|
||||||
|
if (draining || queue.length === 0) return;
|
||||||
|
draining = true;
|
||||||
|
authFailed = false;
|
||||||
|
try {
|
||||||
|
for (const e of queue.slice()) {
|
||||||
|
if (e.op === "delete") await pushDelete(e.key);
|
||||||
|
else await pushBookmark(e.key, e.sendStatus);
|
||||||
|
if (authFailed) {
|
||||||
|
toast("Sync auth failed — check the token", true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
draining = false;
|
||||||
|
}
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Mutations (optimistic: update UI/cache first, then sync)
|
// Mutations (optimistic: update UI/cache first, then sync)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -1018,6 +1043,9 @@
|
|||||||
// Asura is client-routed, so full loads are rare — checking here too is
|
// Asura is client-routed, so full loads are rare — checking here too is
|
||||||
// what keeps its bookmarks current. The throttle still caps the rate.
|
// what keeps its bookmarks current. The throttle still caps the rate.
|
||||||
backgroundRefreshLatest();
|
backgroundRefreshLatest();
|
||||||
|
// Drain only, not a full refresh: Asura may go a long time without a
|
||||||
|
// reload, and an extra GET per client-side route change is not wanted.
|
||||||
|
drain();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Framework-agnostic URL-change watcher: patch history + poll as a fallback,
|
// Framework-agnostic URL-change watcher: patch history + poll as a fallback,
|
||||||
@@ -1053,6 +1081,7 @@
|
|||||||
state.page = detect();
|
state.page = detect();
|
||||||
render();
|
render();
|
||||||
installNavWatcher();
|
installNavWatcher();
|
||||||
|
window.addEventListener("online", drain); // signal returned while the page stayed open
|
||||||
// Sync first: both auto-record and the latest-chapter checks below need to
|
// Sync first: both auto-record and the latest-chapter checks below need to
|
||||||
// know which series are bookmarked and how fresh they are.
|
// know which series are bookmarked and how fresh they are.
|
||||||
refresh().then(() => {
|
refresh().then(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user