Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions staged/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,16 @@ async fn start_workspace(
match blox::ws_start(ws_name, resolved_source.as_deref()) {
Ok(_) => Ok(()),
Err(e) => {
let _ =
store.update_branch_workspace_status(&branch.id, &store::WorkspaceStatus::Error);
Err(format!("Failed to start workspace: {e}"))
// Don't set Error status here — `blox ws start` can fail (e.g.
// timeout, transient network issue) even though the workspace was
// created and is still booting. Let the frontend's status polling
// determine the real state; it will keep polling while the DB says
// Starting and will eventually converge on the correct status.
log::warn!(
"blox ws start failed for '{}', leaving status as Starting for polling to resolve: {e}",
ws_name
);
Ok(())
}
}
}
Expand Down Expand Up @@ -829,7 +836,24 @@ async fn poll_workspace_status(
.as_deref()
.ok_or("Branch is not a remote workspace branch")?;

let info = blox::ws_info(ws_name).map_err(|e| e.to_string())?;
let info = match blox::ws_info(ws_name) {
Ok(info) => info,
Err(e) => {
// During initial creation, `blox ws start` may still be running
// when the frontend's first poll fires `blox ws info`. The
// workspace doesn't exist yet, so the CLI returns "not found".
// If the DB still says Starting, swallow the error and tell the
// frontend to keep polling.
if branch.workspace_status == Some(store::WorkspaceStatus::Starting) {
log::debug!(
"blox ws info failed for '{}' while still Starting, treating as Starting: {e}",
ws_name
);
return Ok(store::WorkspaceStatus::Starting.as_str().to_string());
}
return Err(e.to_string());
}
};

// Map the CLI-reported status to our enum.
// During initial startup, Blox may briefly report "stopped" before the
Expand Down
29 changes: 25 additions & 4 deletions staged/src/lib/RemoteBranchCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
let polledStatus = $state<WorkspaceStatus | null>(null);
let status = $derived<WorkspaceStatus | null>(polledStatus ?? branch.workspaceStatus);
let pollTimer: ReturnType<typeof setInterval> | null = null;
let pollStartedAt: number | null = null;
const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes

// Error state
let error = $state<string | null>(null);
Expand Down Expand Up @@ -130,7 +132,18 @@

function startPolling() {
stopPolling();
pollStartedAt = Date.now();
pollTimer = setInterval(async () => {
// Safety valve: stop polling after timeout to avoid infinite loops
// when a workspace never materializes.
if (pollStartedAt && Date.now() - pollStartedAt > POLL_TIMEOUT_MS) {
console.error('Workspace polling timed out after 5 minutes');
polledStatus = 'error';
error = 'Workspace provisioning timed out';
stopPolling();
return;
}

try {
const newStatus = (await commands.pollWorkspaceStatus(branch.id)) as WorkspaceStatus;
polledStatus = newStatus;
Expand All @@ -141,10 +154,18 @@
stopPolling();
}
} catch (e) {
console.error('Failed to poll workspace status:', e);
polledStatus = 'error';
error = e instanceof Error ? e.message : String(e);
stopPolling();
// During initial creation, `blox ws start` may still be running
// when the first poll fires. The backend tolerates this when the
// DB status is Starting, but as a safety net we also keep polling
// on the frontend side if our local status is still 'starting'.
if (status === 'starting') {
console.debug('Poll failed while starting (workspace may not exist yet), retrying…', e);
} else {
console.error('Failed to poll workspace status:', e);
polledStatus = 'error';
error = e instanceof Error ? e.message : String(e);
stopPolling();
}
}
}, 3000);
}
Expand Down