const RECOVERABLE_KINDS = new Set(["CHUNK_LOAD_FAILURE", "DEPLOY_MISMATCH"]); /** * @typedef {{action: "reload-once", releasePair: string} | * {action: "support", reason: string}} ChunkRecoveryDecision */ /** * @param {{ * failureKind: string, * manifestLoaded: boolean, * currentBuildId: string, * currentReleaseId: string, * activeBuildId: string, * activeReleaseId: string, * storage: import("../ports/storage-port.js").StoragePort * }} input * @returns {ChunkRecoveryDecision} */ export function decideChunkRecovery(input) { if (!RECOVERABLE_KINDS.has(input.failureKind)) { return { action: "support", reason: "not-recoverable" }; } if (!input.manifestLoaded) { return { action: "support", reason: "manifest-unavailable" }; } if ( input.activeBuildId === input.currentBuildId && input.activeReleaseId === input.currentReleaseId ) { return { action: "support", reason: "same-release" }; } const releasePair = `${input.currentBuildId}/${input.currentReleaseId}` + `->${input.activeBuildId}/${input.activeReleaseId}`; const guard = input.storage.read("CHUNK_RELOAD_GUARD"); if (!guard.ok) { return { action: "support", reason: "guard-read-failed" }; } if (guard.value === releasePair) { return { action: "support", reason: "reload-already-attempted" }; } const recorded = input.storage.write("CHUNK_RELOAD_GUARD", releasePair); if (!recorded.ok) { return { action: "support", reason: "guard-write-failed" }; } return { action: "reload-once", releasePair }; }