fix(ui): serialize active-server activations to guarantee ordering
Aborting a fetch can't stop a POST already running server-side, so a stale activation could still land last. Chain the requests so each runs after the previous resolves — the latest navigation's activation is always last. A 5s per-request timeout keeps a hung request from stalling the chain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feat/v1-foundation
parent
f4c24d51a6
commit
a69551a7eb
|
|
@ -202,18 +202,23 @@ document.addEventListener('alpine:init', () => {
|
|||
// Keep the active-server session in sync with the server-details page on screen, even
|
||||
// when wire:navigate restores a page from its bfcache (Back/Forward) without re-running
|
||||
// Show::mount(). The details page tags its root with data-clusev-activate=<activate URL>.
|
||||
let clusevActivateAbort;
|
||||
let clusevActivateChain = Promise.resolve();
|
||||
document.addEventListener('livewire:navigated', () => {
|
||||
// Abort any prior in-flight activation so only the LATEST navigation can win — a
|
||||
// stale request must never overwrite a newer server selection.
|
||||
clusevActivateAbort?.abort();
|
||||
const el = document.querySelector('[data-clusev-activate]');
|
||||
if (!el) return;
|
||||
clusevActivateAbort = new AbortController();
|
||||
const token = document.querySelector('meta[name="csrf-token"]')?.content;
|
||||
fetch(el.dataset.clusevActivate, {
|
||||
const url = el.dataset.clusevActivate;
|
||||
const token = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
|
||||
// SERIALIZE: run each activation after the previous one resolves, so the LATEST
|
||||
// navigation's request is guaranteed to reach the server last — a stale activation
|
||||
// can never overwrite a newer selection. A per-request timeout prevents a hung
|
||||
// request from stalling the chain.
|
||||
clusevActivateChain = clusevActivateChain.then(() => {
|
||||
const ctrl = new AbortController();
|
||||
const timer = setTimeout(() => ctrl.abort(), 5000);
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-TOKEN': token ?? '', 'X-Requested-With': 'XMLHttpRequest' },
|
||||
signal: clusevActivateAbort.signal,
|
||||
}).catch(() => {});
|
||||
headers: { 'X-CSRF-TOKEN': token, 'X-Requested-With': 'XMLHttpRequest' },
|
||||
signal: ctrl.signal,
|
||||
}).catch(() => {}).finally(() => clearTimeout(timer));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue