T2.3: Split domain.Job (durable) from domain.JobRuntime (transient)
Move all transient execution state off domain.Job into a new domain.JobRuntime, keyed by job ID: - domain: Job now holds only durable YAML fields; remove the yaml:"-" fields (LastRun/NextRun/LastState/Logs/Output) and NextDue. Add runtime.go with JobRuntime plus NewRuntime/NewRuntimes constructors, which now own the runtime-init logic moved out of normalizeJobs. - runner: RunJob no longer mutates the job; it is pure and returns the RunRecord for the caller to fold into the runtime. - scheduler: take a shared map[int]*JobRuntime and route status/next-run bookkeeping through runtimeFor(job); prepareNextRun writes a *JobRuntime. - storage: normalizeJobs touches only durable config. - gui: own the runtime map (NewRuntimes), share it with the scheduler, and read/write runtime state via runtimeFor; maintain the map by ID on add/edit/delete. - tests: update scheduler/storage tests to the split; tidy a pre-existing import-order nit in scheduler.go. This also satisfies T2.4 (storage load/save only Job, runtime init in domain.NewRuntime, round-trip tests), since removing the fields forced it. Runtime-map ownership remains GUI-side glue until T3.1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+6
-13
@@ -49,13 +49,14 @@ func RunJob(ctx context.Context, job *domain.Job, trigger string, logsDir string
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
job.LastRun = now.Format("2006-01-02 15:04:05")
|
||||
job.LastState = state
|
||||
job.Output = output
|
||||
timestamp := now.Format("2006-01-02 15:04:05")
|
||||
logFile := writeRunLog(logsDir, *job, trigger, state, detail, output, now)
|
||||
|
||||
record := domain.RunRecord{
|
||||
Time: job.LastRun,
|
||||
// The runner is now pure with respect to the job: it returns a RunRecord and
|
||||
// lets the caller fold that record into the job's JobRuntime. Run state no
|
||||
// longer lives on Job, so there is nothing on the job to mutate here.
|
||||
return domain.RunRecord{
|
||||
Time: timestamp,
|
||||
JobID: job.ID,
|
||||
JobName: job.Name,
|
||||
Trigger: trigger,
|
||||
@@ -64,14 +65,6 @@ func RunJob(ctx context.Context, job *domain.Job, trigger string, logsDir string
|
||||
LogFile: logFile,
|
||||
Output: output,
|
||||
}
|
||||
// Keep a small in-memory history for the currently running GUI. Full command
|
||||
// output is persisted to files, so retaining every past record in RAM would
|
||||
// only duplicate data and make long sessions grow without bound.
|
||||
job.Logs = append([]domain.RunRecord{record}, job.Logs...)
|
||||
if len(job.Logs) > 50 {
|
||||
job.Logs = job.Logs[:50]
|
||||
}
|
||||
return record
|
||||
}
|
||||
|
||||
func startJobOnly(invocation commandInvocation, job domain.Job, started time.Time) (string, string, string) {
|
||||
|
||||
Reference in New Issue
Block a user