loopd: cron tick, new session per run
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
use crate::baseline::Baseline;
|
||||
use crate::channel::{Busy, Context};
|
||||
use crate::compact;
|
||||
use crate::cron;
|
||||
use crate::jobs::{self, Run, RunStatus};
|
||||
use crate::session::{Session, SessionError};
|
||||
use crate::turn::{Runtime, run_turn};
|
||||
@@ -42,6 +43,133 @@ impl Scheduler {
|
||||
self.leftovers_closed = true;
|
||||
}
|
||||
self.heartbeat(ctx, now, &mut work);
|
||||
|
||||
let jobs_dir = ctx.cfg.paths.home.join("jobs");
|
||||
let runs_path = jobs_dir.join("runs.jsonl");
|
||||
let jobs = match jobs::load(&jobs_dir) {
|
||||
Ok(jobs) => jobs,
|
||||
Err(e) => {
|
||||
eprintln!("loopd: {e}");
|
||||
return work;
|
||||
}
|
||||
};
|
||||
for job in &jobs {
|
||||
match cron::due(&job.schedule, now) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => continue,
|
||||
Err(e) => {
|
||||
eprintln!("loopd: {e}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
match jobs::live_session(&runs_path, &job.name) {
|
||||
Ok(Some(_)) => {
|
||||
work.push(TickWork::SkippedJob {
|
||||
name: job.name.clone(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(e) => {
|
||||
eprintln!("loopd: cannot read the live session for {}: {e}", job.name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let id = match jobs::session_id(&job.name, now) {
|
||||
Ok(id) => id,
|
||||
Err(e) => {
|
||||
eprintln!("loopd: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let held = match ctx.hold(id.clone()) {
|
||||
Ok(held) => held,
|
||||
Err(Busy) => {
|
||||
work.push(TickWork::SkippedJob {
|
||||
name: job.name.clone(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let baseline = match Baseline::assemble(&ctx.cfg, &ctx.registry) {
|
||||
Ok(baseline) => baseline,
|
||||
Err(e) => {
|
||||
eprintln!("loopd: job {} baseline: {e}", job.name);
|
||||
drop(held);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let mut session = match Session::create(
|
||||
&ctx.cfg.paths.home,
|
||||
id.clone(),
|
||||
baseline,
|
||||
ctx.cfg.slots.background,
|
||||
) {
|
||||
Ok(session) => session,
|
||||
Err(SessionError::Exists(_)) => {
|
||||
match Session::open(&ctx.cfg.paths.home, id.clone()) {
|
||||
Ok(session) => session,
|
||||
Err(e) => {
|
||||
eprintln!("loopd: job {} session {}: {e}", job.name, id.as_str());
|
||||
drop(held);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("loopd: job {} session {}: {e}", job.name, id.as_str());
|
||||
drop(held);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let _ = jobs::append(
|
||||
&runs_path,
|
||||
&Run {
|
||||
time: now,
|
||||
name: job.name.clone(),
|
||||
session: id.clone(),
|
||||
status: RunStatus::Started,
|
||||
},
|
||||
);
|
||||
let runtime = Runtime {
|
||||
cfg: &ctx.cfg,
|
||||
client: &ctx.client,
|
||||
port: &*ctx.port,
|
||||
registry: &ctx.registry,
|
||||
};
|
||||
let text = format!("It is {}.\n\n{}", now.to_rfc3339(), job.prompt);
|
||||
let mut emit = |_event: &TurnEvent| {};
|
||||
let outcome = run_turn(&mut session, &runtime, &text, None, &mut emit);
|
||||
let outcome = compact::finish_turn(
|
||||
&mut session,
|
||||
&runtime,
|
||||
&*ctx.memory,
|
||||
&text,
|
||||
None,
|
||||
&mut emit,
|
||||
outcome,
|
||||
);
|
||||
let status = if outcome.is_ok() {
|
||||
RunStatus::Finished
|
||||
} else {
|
||||
RunStatus::Failed
|
||||
};
|
||||
let _ = jobs::append(
|
||||
&runs_path,
|
||||
&Run {
|
||||
time: now,
|
||||
name: job.name.clone(),
|
||||
session: id.clone(),
|
||||
status,
|
||||
},
|
||||
);
|
||||
drop(held);
|
||||
work.push(TickWork::Job {
|
||||
name: job.name.clone(),
|
||||
session: id,
|
||||
});
|
||||
}
|
||||
|
||||
work
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user