fix: harden run persistence and error surfacing from code review

Snapshot store paths under lock before async runs, roll back failed
start/save state, emit UI events only after successful persistence,
surface log write failures, and sync stale YAML docs to JSON.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mixeme
2026-06-29 21:33:50 +03:00
parent 09c5edc993
commit e9fc9eaba0
16 changed files with 230 additions and 88 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ func newEvent(jobID int, jobName string, state string, detail string) event {
func collectActivity(jobs []job, runtimes map[int]*domain.JobRuntime) []event {
var events []event
for _, current := range jobs {
// At startup this is usually empty because jobs.yaml does not persist
// At startup this is usually empty because jobs.json does not persist
// runtime logs. The function still centralizes the merge for future
// history loading from log metadata.
if rt := runtimes[current.ID]; rt != nil {
+2 -2
View File
@@ -43,8 +43,8 @@ func newMainView(w fyne.Window) (fyne.CanvasObject, func(time.Duration, bool)) {
history, refreshHistory := newHistoryView(&events)
recordStartup := func(duration time.Duration, windowShown bool) {
// Startup is recorded as an in-memory History event instead of being
// persisted into jobs.yaml. It is session diagnostics, not durable job
// state, and keeping it ephemeral avoids polluting the human-editable YAML
// persisted into jobs.json. It is session diagnostics, not durable job
// state, and keeping it ephemeral avoids polluting the human-editable JSON
// file with process-lifetime bookkeeping.
detail := "Window shown in " + duration.Round(time.Millisecond).String()
if !windowShown {
+1 -1
View File
@@ -196,7 +196,7 @@ func settingsView(w fyne.Window, svc *app.Service) fyne.CanvasObject {
// gap between them instead of merging into one block.
container.NewVBox(
widget.NewLabelWithStyle("Storage", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
settingsRow("Config YAML", widget.NewLabel(store.Paths.ConfigPath)),
settingsRow("Config JSON", widget.NewLabel(store.Paths.ConfigPath)),
settingsRow("Jobs directory", container.NewBorder(nil, nil, nil, jobsDirBrowse, jobsDir)),
settingsRow("Logs directory", container.NewBorder(nil, nil, nil, logsDirBrowse, logsDir)),
settingsRow("Max log files", maxLogFiles),