This adds a circuit breaker for uncaught failures in beforeEach. The first failure still goes through the normal ERROR/RESTART recovery path; a second consecutive failure redirects to the static error page instead of looping. - New before-each-error-recovery module tracks recovery attempts in sessionStorage (with an in-memory fallback). - ERROR/RESTART routes skip normal guard logic so the counter can accumulate across bounce-backs. - The counter clears only after a fully successful navigation. - redirectToStaticErrorPage centralizes hard-error bailout: logs, clears poisoned sessionStorage keys (submittedState, heritage redirect count, recovery count, externalParameterState), then navigates to /fmg/static/error. - The static error page RESTART flow clears the same sessionStorage keys so bad state does not re-enter the funnel. - Session storage key strings are centralized in session-storage.js. - Unit tests cover recovery counting, bailout clearing, and navigation fallbacks. Expected impact: Stops repeated ERROR → RESTART → ERROR cycles (including corrupt submittedState JSON.parse failures and recurring automation errors in us-east-1/us-east-2) by bailing out to the static error page after one failed recovery attempt.
51 lines
1.5 KiB
JavaScript
51 lines
1.5 KiB
JavaScript
import { sessionStorageKeyConstants } from "@/constants/session-storage";
|
|
|
|
const recoveryKey = sessionStorageKeyConstants.BEFORE_EACH_ERROR_RECOVERY_COUNT;
|
|
|
|
/** Used when sessionStorage is missing, throws, or does not persist (e.g. some bots). */
|
|
let inMemoryRecoveryCount = 0;
|
|
|
|
export function getBeforeEachErrorRecoveryCount() {
|
|
try {
|
|
const stored = window.sessionStorage?.getItem(recoveryKey);
|
|
if (stored !== null && stored !== undefined) {
|
|
return Number(stored) || 0;
|
|
}
|
|
} catch {
|
|
// sessionStorage unavailable; use in-memory fallback
|
|
}
|
|
|
|
return inMemoryRecoveryCount;
|
|
}
|
|
|
|
export function incrementBeforeEachErrorRecoveryCount() {
|
|
const nextCount = getBeforeEachErrorRecoveryCount() + 1;
|
|
inMemoryRecoveryCount = nextCount;
|
|
|
|
try {
|
|
window.sessionStorage?.setItem(recoveryKey, String(nextCount));
|
|
} catch {
|
|
// in-memory count already updated
|
|
}
|
|
|
|
return nextCount;
|
|
}
|
|
|
|
export function clearBeforeEachErrorRecoveryCount() {
|
|
inMemoryRecoveryCount = 0;
|
|
|
|
try {
|
|
window.sessionStorage?.removeItem(recoveryKey);
|
|
} catch {
|
|
// in-memory count already cleared
|
|
}
|
|
}
|
|
|
|
export function hasBeforeEachErrorRecoveryBeenAttempted() {
|
|
return getBeforeEachErrorRecoveryCount() >= 1;
|
|
}
|
|
|
|
/** Test-only: resets in-memory and sessionStorage recovery state between unit tests. */
|
|
export function resetBeforeEachErrorRecoveryStateForTests() {
|
|
clearBeforeEachErrorRecoveryCount();
|
|
}
|