DEV Community
Follow
A stale "checking..." restored from disk is a lie, so one of our six stores has no file
Notifio is a desktop application designed to monitor rental search pages and alert users to new listings. It manages six distinct pieces of application state, each with unique rules for its lifespan. These rules are derived from the fundamental question of what each state represents.Configuration settings like searches, email, and the license are stored in config.json and persist across all operations. The baseline of a search page is saved to disk but is not trusted after the application restarts, being re-evaluated on the next check. Recent finds are stored in finds.json and are designed to survive application restarts and search re-pointing, acting as a crucial history.A reply ledger, stored in ledger/replies.ndjson, tracks outgoing messages and is append-only to ensure data integrity after crashes, with compaction handling its growth. Upgrade entitlement is saved in entitlement.json and includes a staleness flag, indicating its validity. Live per search run state, which tracks current checks and statuses, is intentionally kept in memory only to avoid presenting stale information.This in-memory state is critical; persisting it after a crash would misrepresent the application's current activity. The stop button clears this live state because the described run has concluded. Changes to this live state are coalesced before being emitted to the renderer to avoid overwhelming it.Each search's page baseline is identified by a hash of its URL, not its position in a list, preventing bugs related to list editing. The age of the baseline is determined by the file's modification timestamp, obviating the need for a separate lastCheckedAt field. Finds and the reply ledger are histories that must not be deleted by actions unrelated to them.The finds history is kept separate from per-search snapshots because re-pointing a search would otherwise erase valuable historical data. The reply ledger's append-only nature with compaction provides crash safety and handles message tracking. Finally, the lifespan of each state is determined by its underlying purpose: user intent, happened events, external world information, or transient real-time data.