Keep held provisioning recovery current (Refs #86)
This commit is contained in:
@@ -15,6 +15,12 @@ export function provisioningRequester(operation: Pick<ProvisioningDeployment, 'r
|
||||
}
|
||||
|
||||
export const activeProvisioningStates = ['queued', 'waiting', 'running', 'awaiting-health'];
|
||||
|
||||
/** A finished restart can still release its recovery slot or hand it to a rebuild. */
|
||||
export function provisioningNeedsRefresh(detail: ProvisioningDetail): boolean {
|
||||
return activeProvisioningStates.includes(detail.deployment.state) || detail.progress?.recovery?.state === 'held';
|
||||
}
|
||||
|
||||
export type ProgressState = 'done' | 'current' | 'waiting' | 'failed' | 'pending' | 'cancelled' | 'unknown';
|
||||
export interface ProgressStep {
|
||||
key: ProvisioningPhase; label: string; state: ProgressState; at: string | null;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import { serverTitle } from '$ui/server-labels.js';
|
||||
import { createProvisioningRefresh, type ProvisioningRefreshState } from '$ui/provisioning-refresh.js';
|
||||
import { confirmAction } from '$ui/confirm.js';
|
||||
import { elapsedTime, isProvisioningDetail, provisioningOutcome, provisioningRequester } from '$ui/provisioning-presentation.js';
|
||||
import { elapsedTime, isProvisioningDetail, provisioningNeedsRefresh, provisioningOutcome, provisioningRequester } from '$ui/provisioning-presentation.js';
|
||||
import SectionHeader from '$ui/components/primitives/SectionHeader.svelte';
|
||||
import Breadcrumbs from '$ui/components/primitives/Breadcrumbs.svelte';
|
||||
import StatusBadge from '$ui/components/primitives/StatusBadge.svelte';
|
||||
@@ -44,6 +44,7 @@
|
||||
const canOverride = $derived(data.user?.role === 'admin' && detail?.canOverrideSafety);
|
||||
const outcome = $derived(detail ? provisioningOutcome(detail) : null);
|
||||
const active = $derived(outcome?.active ?? false);
|
||||
const needsRefresh = $derived(detail ? provisioningNeedsRefresh(detail) : false);
|
||||
const duration = $derived(finishedAt || active ? elapsedTime(startedAt, finishedAt ? Date.parse(finishedAt) : now) : 'Not recorded');
|
||||
const serverHref = $derived(deployment && deployment.server_exists && !deployment.server_deleted_at ? `/servers/${encodeURIComponent(deployment.server)}` : null);
|
||||
const recipeStatus = $derived(detail?.progress?.recipeStatus ?? null);
|
||||
@@ -58,7 +59,7 @@
|
||||
});
|
||||
});
|
||||
$effect(() => {
|
||||
if (!active) return;
|
||||
if (!needsRefresh) return;
|
||||
return pollVisible(() => { now = Date.now(); return controller.refresh(); }, 5000, false);
|
||||
});
|
||||
onDestroy(() => controller.dispose());
|
||||
@@ -149,7 +150,6 @@
|
||||
{#if detail.progress?.recovery}<div class="recovery-note"><strong>{detail.progress.recovery.state === 'held' ? 'Recovery remains in progress' : detail.progress.recovery.state === 'released' ? 'Recovery capacity released' : detail.progress.recovery.state === 'transferred' ? 'Recovery transferred' : 'Recovery state not confirmed'}</strong><p>{detail.progress.recovery.message}</p><span>Recorded <OperationTime start={deployment.started_at} value={detail.progress.recovery.at} missing="Not recorded" /></span>{#if detail.progress.recovery.operationId && detail.progress.recovery.operationId !== deployment.id}<a href={`/provisioning/${encodeURIComponent(detail.progress.recovery.operationId)}`}>View recovery operation →</a>{/if}</div>{/if}
|
||||
{#if serverHref && !['done', 'cancelled'].includes(deployment.state)}<div class="diagnostics"><a href={`${serverHref}?tab=logs`}>Open server logs</a><a href={`${serverHref}?tab=diagnostics`}>Diagnose connection</a>{#if detail.progress?.phase === 'verify-map' || detail.progress?.checks.some(check => check.key === 'map' && check.result !== 'pass')}<a href={`${serverHref}?tab=config`}>Review map configuration</a>{/if}</div>{/if}
|
||||
<div class="timing">
|
||||
<div><span>{outcome.active ? 'Total elapsed' : 'Recorded duration'}</span><strong>{duration}</strong></div>
|
||||
{#if outcome.active}<div><span>Time in phase</span><strong>{elapsedTime(timestampISO(detail.progress?.phaseStartedAt), now)}</strong></div>{/if}
|
||||
<div><span>Last evaluated</span><OperationTime start={deployment.started_at} value={detail.progress?.observedAt} missing="Not recorded" /></div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user