mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-12 15:53:46 -04:00
Read the running version from the container that answers the status request, not from the old page state, so the modal shows success as soon as the new version is up. Hide all Livewire error pages while an upgrade runs. Closes #8024 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
2.9 KiB
JavaScript
76 lines
2.9 KiB
JavaScript
export const INFRASTRUCTURE_FAILURE_STATUSES = new Set([502, 503, 504, 520, 521, 522, 523, 524, 525, 526, 527, 530]);
|
|
|
|
const USER_GESTURE_EVENTS = ['click', 'submit', 'keydown', 'input', 'change'];
|
|
|
|
// A request sent within this window of a trusted user gesture is treated as
|
|
// user-initiated. It must cover Alpine $nextTick deferrals and wire:model
|
|
// debounces, while staying short enough to exclude most wire:poll requests.
|
|
export const GESTURE_WINDOW_MS = 2_000;
|
|
|
|
const WARN_COOLDOWN_MS = 10_000;
|
|
const WARN_CONTENT_MAX_LENGTH = 2_000;
|
|
|
|
export function createLivewireRequestFailureHandler({ now = Date.now } = {}) {
|
|
let lastWarnAt = Number.NEGATIVE_INFINITY;
|
|
let lastToastGestureAt = Number.NEGATIVE_INFINITY;
|
|
|
|
return ({ status, content, preventDefault, gestureAt = Number.NEGATIVE_INFINITY }) => {
|
|
// While Coolify restarts for an upgrade, any request can fail (proxy errors, then the new
|
|
// version answering the old page). The upgrade modal shows the progress, so show no error page.
|
|
if (window.coolifyUpgradeInProgress) {
|
|
preventDefault();
|
|
return;
|
|
}
|
|
|
|
if (!INFRASTRUCTURE_FAILURE_STATUSES.has(status)) {
|
|
return;
|
|
}
|
|
|
|
preventDefault();
|
|
|
|
const currentTime = now();
|
|
if (currentTime - lastWarnAt >= WARN_COOLDOWN_MS) {
|
|
lastWarnAt = currentTime;
|
|
console.warn('Livewire request failed', {
|
|
status,
|
|
content: typeof content === 'string' ? content.slice(0, WARN_CONTENT_MAX_LENGTH) : content,
|
|
});
|
|
}
|
|
|
|
// One toast per user gesture: a single click that fails several
|
|
// component requests toasts once, while a retry (a new gesture)
|
|
// always toasts again. Background requests carry no gesture.
|
|
if (gestureAt > lastToastGestureAt) {
|
|
lastToastGestureAt = gestureAt;
|
|
window.toast?.('Action could not be completed', {
|
|
type: 'danger',
|
|
description: 'Coolify did not receive a response. Please try again.',
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
export function registerLivewireRequestFailureHandler(Livewire, documentObject = document, { now = Date.now } = {}) {
|
|
let lastGestureAt = Number.NEGATIVE_INFINITY;
|
|
|
|
const markUserGesture = (event) => {
|
|
if (event.isTrusted) {
|
|
lastGestureAt = now();
|
|
}
|
|
};
|
|
|
|
USER_GESTURE_EVENTS.forEach((eventName) => {
|
|
documentObject.addEventListener(eventName, markUserGesture, true);
|
|
});
|
|
|
|
const handleFailure = createLivewireRequestFailureHandler({ now });
|
|
|
|
Livewire.hook('request', ({ fail }) => {
|
|
// Classify at send time: infrastructure failures (522/524) can arrive
|
|
// long after the gesture, so the failure timestamp is meaningless.
|
|
const gestureAt = now() - lastGestureAt <= GESTURE_WINDOW_MS ? lastGestureAt : Number.NEGATIVE_INFINITY;
|
|
|
|
fail((failure) => handleFailure({ ...failure, gestureAt }));
|
|
});
|
|
}
|