reconcileAutoRun promotes a stale 'running' row to 'dead' when its supervisor pid is no longer alive (crash, kill -9, reboot — anything that prevented finalizeAutoRun from running). No-op for any other state. Mutates both the DB and the in-memory task. Best-effort: DB errors leave the in-memory copy
(db *sql.DB, t *flowdb.Task)
| 191 | return err |
| 192 | } |
| 193 | |
| 194 | // reconcileAutoRun promotes a stale 'running' row to 'dead' when its |
| 195 | // supervisor pid is no longer alive (crash, kill -9, reboot — anything |
| 196 | // that prevented finalizeAutoRun from running). No-op for any other |
| 197 | // state. Mutates both the DB and the in-memory task. Best-effort: DB |
| 198 | // errors leave the in-memory copy untouched. |
| 199 | func reconcileAutoRun(db *sql.DB, t *flowdb.Task) { |
| 200 | if !t.AutoRunStatus.Valid || t.AutoRunStatus.String != "running" { |
| 201 | return |
| 202 | } |
| 203 | if t.AutoRunPID.Valid && processAlive(int(t.AutoRunPID.Int64)) { |
| 204 | return |
| 205 | } |
| 206 | now := flowdb.NowISO() |
| 207 | if _, err := db.Exec( |
| 208 | `UPDATE tasks SET auto_run_status='dead', auto_run_finished=COALESCE(auto_run_finished, ?), |
| 209 | auto_run_pid=NULL WHERE slug=? AND auto_run_status='running'`, |
| 210 | now, t.Slug, |
| 211 | ); err != nil { |
| 212 | return |
| 213 | } |
| 214 | t.AutoRunStatus = sql.NullString{String: "dead", Valid: true} |
| 215 | if !t.AutoRunFinished.Valid { |
| 216 | t.AutoRunFinished = sql.NullString{String: now, Valid: true} |