fix: p attach on dead/unknown sessions
This commit is contained in:
@@ -11,20 +11,23 @@ pub fn execute(job_id: &str) -> Result<()> {
|
|||||||
let cfg = config::load()?;
|
let cfg = config::load()?;
|
||||||
let job = db::find(job_id)?.with_context(|| format!("job '{}' not found", job_id))?;
|
let job = db::find(job_id)?.with_context(|| format!("job '{}' not found", job_id))?;
|
||||||
|
|
||||||
if job.status != JobStatus::Running {
|
// Allow attach on Running (normal) and Unknown (worker was temporarily
|
||||||
anyhow::bail!(
|
// unreachable — the job may still be live).
|
||||||
|
match job.status {
|
||||||
|
JobStatus::Running | JobStatus::Unknown => {}
|
||||||
|
_ => anyhow::bail!(
|
||||||
"job {} is not running (status: {})\n\
|
"job {} is not running (status: {})\n\
|
||||||
use 'p logs {}' to view its output",
|
use 'p logs {}' to view its output",
|
||||||
job.short_id(),
|
job.short_id(),
|
||||||
job.status.as_str(),
|
job.status.as_str(),
|
||||||
job.short_id(),
|
job.short_id(),
|
||||||
);
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
let worker = cfg.resolve_worker(Some(&job.worker))?.clone();
|
let worker = cfg.resolve_worker(Some(&job.worker))?.clone();
|
||||||
let session = format!("p-{}", job.short_id());
|
let session = format!("p-{}", job.short_id());
|
||||||
|
|
||||||
let sid = job.short_id().to_string();
|
let sid = job.short_id().to_string();
|
||||||
|
|
||||||
{
|
{
|
||||||
let sid = sid.clone();
|
let sid = sid.clone();
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
@@ -36,9 +39,30 @@ pub fn execute(job_id: &str) -> Result<()> {
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh::run_interactive(&worker, &format!("tmux attach -t '{}'", session))?;
|
let attach_status = ssh::run_interactive(&worker, &format!("tmux attach -t '{}'", session))?;
|
||||||
|
|
||||||
|
// If tmux exited non-zero the session doesn't exist on the worker.
|
||||||
|
if !attach_status.success() {
|
||||||
|
let exit_code = ssh::read_job_exitcode(&worker, &job.id);
|
||||||
|
if exit_code.is_none() {
|
||||||
|
// No exit code either — the job was lost without completing
|
||||||
|
// (e.g. worker restarted, tmux server killed).
|
||||||
|
eprintln!(
|
||||||
|
"error: tmux session for job {} no longer exists on '{}'.",
|
||||||
|
sid, worker.name
|
||||||
|
);
|
||||||
|
eprintln!("The job was likely interrupted (worker restart or tmux server exit).");
|
||||||
|
eprintln!("Use 'p logs {}' to see whatever output was captured.", sid);
|
||||||
|
db::save(&Job {
|
||||||
|
status: JobStatus::Unknown,
|
||||||
|
..job
|
||||||
|
})?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// Exit code exists — job finished cleanly but the session was already
|
||||||
|
// cleaned up. Fall through to normal reconciliation.
|
||||||
|
}
|
||||||
|
|
||||||
// Same reconciliation logic as the run command.
|
|
||||||
let exit_code = ssh::read_job_exitcode(&worker, &job.id);
|
let exit_code = ssh::read_job_exitcode(&worker, &job.id);
|
||||||
let now = Utc::now().timestamp();
|
let now = Utc::now().timestamp();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user