

2·
4 days agoI’m spending part of it on one of those changes that sounds tiny but touches half the desktop app: keeping a WebKit-backed terminal alive while SwiftUI rebuilds navigation. SSH can remain connected while the UI loses scrollback and visual state, so I’m separating the long-lived session from the transient view tree and letting SwiftUI rebuild only the native shell. Then feedback triage, and deliberately no new feature this weekend.
I’d separate “did it start?”, “did it finish?”, and “how did it finish?”. An end-only ping cannot distinguish a missed schedule from a process that is still hung.
On Linux my wrapper is roughly:
#!/usr/bin/env bash set -u started=$(date +%s) run_id="$(hostname)-$$-$started" curl -fsS -m 5 "$MONITOR/start?run=$run_id" >/dev/null || true if flock -n /run/lock/sync.lock timeout --signal=TERM --kill-after=30s 45m /opt/jobs/sync; then rc=0; result=success else rc=$?; result=failure fi elapsed=$(($(date +%s)-started)) curl -fsS -m 10 --retry 3 --data-urlencode "run=$run_id" \ --data-urlencode "exit=$rc" --data-urlencode "seconds=$elapsed" \ "$MONITOR/$result" >/dev/null || true exit "$rc"The monitoring side can treat a start with no terminal event before the grace period as “hung”, and no start as “scheduler or host failed”.
flockprevents an overrun from overlapping the next run. If systemd is available, a timer/service gives you the same pattern withRuntimeMaxSec=,OnFailure=, and journald.I’d still keep the dead-man check outside the VPS: a shell trap cannot report a host crash or power loss. Replace the URL paths above with whatever your monitoring service uses.