package web import ( "gitgud.io/mike/mpv-manager/pkg/jobhistory" "gitgud.io/mike/mpv-manager/pkg/log" ) // NewJobManagerWithStore creates a job manager that persists terminal jobs to // the store file at path and reloads them into the recent-jobs history. // A missing or corrupt store file is tolerated: it is logged and the history // starts empty (startup never fails because of the store). func NewJobManagerWithStore(path string) *JobManager { jm := NewJobManager() jm.store = jobhistory.NewStore(path) records, err := jm.store.LoadRecords() if err != nil { log.Warn("Failed to load job history, starting empty: " + err.Error()) records = nil } // Records are stored oldest-first; recentJobs expects newest-first, which // LoadRecords already provides. if len(records) > maxRecentJobs { records = records[:maxRecentJobs] } jobs := make([]*Job, 0, len(records)) for _, rec := range records { jobs = append(jobs, recordToJob(rec)) } jm.recentJobs = jobs return jm } // newJobManagerWithHistory creates a JobManager that persists job history in // the mpv config directory (honoring custom config paths). Falls back to // in-memory history when the config directory cannot be resolved. func newJobManagerWithHistory() *JobManager { path, err := jobhistory.FilePath() if err != nil { log.Warn("Job history persistence disabled, cannot resolve mpv config dir: " + err.Error()) return NewJobManager() } return NewJobManagerWithStore(path) } // jobToRecord converts a terminal job to its on-disk record. The store caps // the persisted output to the last jobhistory.MaxOutputLines lines. func jobToRecord(job *Job) jobhistory.Record { return jobhistory.Record{ ID: job.ID, Type: job.Type, MethodID: job.MethodID, AppName: job.AppName, Status: job.Status, Phase: job.Phase, Progress: job.Progress, Message: job.Message, Output: append([]string(nil), job.Output...), Error: job.Error, ErrorDetails: job.ErrorDetails, StartedAt: job.StartedAt, CompletedAt: job.CompletedAt, } } // recordToJob converts a persisted record back into a terminal Job. The job // has no context (it can never be running again); Cancel and IsCancelled // tolerate a nil context. func recordToJob(rec jobhistory.Record) *Job { return &Job{ ID: rec.ID, Type: rec.Type, MethodID: rec.MethodID, AppName: rec.AppName, Status: rec.Status, Phase: rec.Phase, Progress: rec.Progress, Message: rec.Message, Output: append([]string(nil), rec.Output...), Error: rec.Error, ErrorDetails: rec.ErrorDetails, StartedAt: rec.StartedAt, CompletedAt: rec.CompletedAt, } }