One rename puts the new file in place, so it is never absent; start-up
reads without the lock. An edit of an account another process removed is
refused; a newer recorded sync result is kept; a change that finds the
file gone or damaged is applied to what the store last read. Busy means a
sharing violation; a read-only file fails at once; a lock held for the
whole wait is an AccountsFileBusyException (CLI exit 4). Settings saves
retry briefly, use a temporary name of their own and leave nothing behind.
Refs #155
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
The store read accounts.json once and wrote that snapshot back on every
change. With the desktop app open, an account added from the CLI was
erased by the app's next write (recording a sync result was enough), and
its token stayed in the vault with nothing pointing at it. A long
`gclo sync --account` did the same to the app, and two app instances to
each other.
- Every change now takes a lock that every gclo process takes
(accounts.json.lock, opened for one process alone), reads the file
again, applies its one change by account id to what the file holds at
that moment, and writes that. A sync result recorded for an account
another process deleted is ignored, not written back.
- A file that cannot be read is no longer taken for a corrupt one. Only
content that is not a valid list of accounts is moved aside. A file in
use is tried again for a short while; one that stays unreadable is left
where it is: the store starts empty and logs why, and a change fails
without writing anything.
- The swap of the new file into place is tried again when something
outside gclo holds the live file for a moment.
settings.json is written beside the file and moved into place, so a crash
mid-write leaves the previous settings. A failed load or save is logged,
and Save says whether it succeeded. The "0 means absent" special case for
the splash duration described something that does not happen (an absent
field keeps the default); the value is simply brought into range.
Tests: the three classes that set GCLO_DATA_DIR for the process now share
one collection, so they never run beside each other.
docs/CLI.md named the wrong folder for accounts.json; corrected.
Closes#155
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>