Skip to content

fix(state-writer): skip atomic rename when content unchanged#94

Merged
d4rken merged 2 commits into
devfrom
fix/state-writer-skip-unchanged
May 18, 2026
Merged

fix(state-writer): skip atomic rename when content unchanged#94
d4rken merged 2 commits into
devfrom
fix/state-writer-skip-unchanged

Conversation

@d4rken

@d4rken d4rken commented May 18, 2026

Copy link
Copy Markdown
Member

Daemons that run under Restart=always with a sleep-then-exit-0 disabled branch (dump978-fa's no_hardware cycle, airplanes-mlat's mlat_enabled_false cycle) re-classify on every restart and call airplanes_write_state with the same decision but a fresh decided_at timestamp. The atomic rename was firing about 1200 times a day on a typical no-978-dongle feeder — invisible on its own, but enough to wake any inotify consumer watching the file (e.g. a systemd .path unit).

The writer now compares the proposed content against the current file with decided_at= lines stripped from both sides and skips the rename when they match. On-disk decided_at stays at the time of the last material decision rather than being touched on every wrapper restart, which is the more meaningful value for status consumers. AIRPLANES_WRITE_STATE_FORCE=1 opts out and restores the always-rename behaviour for any caller that needs it.

No API change. Every current call-site keeps the same arguments; the dedupe is invisible to them. Mode 0644 is still enforced on rename and the validation-failure paths still short-circuit before the dedupe check.

Wrappers under Restart=always with a sleep+exit-0 disabled branch (dump978-fa's no_hardware loop, airplanes-mlat's mlat_enabled_false loop) re-classify on every cycle and call airplanes_write_state with the same decision but a fresh decided_at timestamp. The atomic rename was firing every ~1200 cycles/day on a typical no-978-dongle feeder, waking any inotify consumer (e.g. systemd .path units watching the file).

Compare the proposed content against the current target ignoring decided_at= lines and skip the rename when they match. Existing on-disk decided_at stays, so consumers see the time of the last material decision rather than the time of the last wrapper restart. AIRPLANES_WRITE_STATE_FORCE=1 keeps the previous always-rename behavior for callers that need it.
@d4rken d4rken added the bug Something isn't working label May 18, 2026
A target left behind without a final newline (interrupted previous write, external tampering) would lose its last line in the bash while-read loop, so a proposed write that removed a tail field could falsely dedupe against the truncated remainder. The `|| [[ -n line ]]` tail picks up the unterminated last line. Regression coverage includes the no-trailing-newline case and a backslashes-plus-trailing-spaces round-trip.
@d4rken d4rken merged commit c300ef0 into dev May 18, 2026
12 checks passed
@d4rken d4rken deleted the fix/state-writer-skip-unchanged branch May 18, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant