Repository navigation
fix(settings): preserve saved state on persistence errors - #198
TimeToBuildBob wants to merge 2 commits into
Conversation
Git-Session-Id: 60032fa4-47fd-4532-ad0e-1cb8be2d15f4
Git-Session-Id: 60032fa4-47fd-4532-ad0e-1cb8be2d15f4
[Medium impact] The changes reach settings persistence and its POST workflow. Fix the concurrency test’s timeout import before merging; it currently fails the Python 3.9 CI jobs. Findings
SummaryThe PR preserves the previous settings file and memory when a save fails.
TimeToBuildBob explicitly deferred native Windows confirmation, cross-process locking, parent-directory fsync, and preservation of hard links or ownership across service users. TimeToBuildBob also stated that this PR does not resolve the original Windows permission report. These acknowledged limits are not findings. Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Settings POST] --> B[Acquire lock and copy saved state]
B --> C[Write, flush, and close temporary file]
C --> D[Replace saved file]
D --> E[Commit memory and release lock]
C -->|Failure| F[Remove temporary file and keep previous state]
D -->|Failure| F
F --> G[Return HTTP 500 for an OSError]
Reviews (1) · Last reviewed commit: "fix(settings): preserve saved state on p..." · Reviewed by Greptile |
🤖 AI code reviewSettings.save() and Settings.set() now serialize writes through an instance lock and persist through a temporary file followed by os.replace(). Settings.set() commits its new dictionary after persistence, while _write() resolves symlinks and copies existing file modes. The REST endpoint adds OSError diagnostics, and the Makefile includes the new settings tests. Needs a look — P2 onlyConfidence 4/5 1 finding ·
|
Convergence adjudication — maintainer decisionRecommendation: retain fail-closed atomic persistence and merge only if the maintainer accepts the writable-target-directory requirement below. No auto-merge or further review round requested.
|
Problem
ActivityWatch/activitywatch#1537 reports settings POSTs failing with
PermissionErroron Windows. The exact file permission/sharing cause still needs reporter diagnosis; this PR does not claim to fix it.While reproducing the persistence path, an interrupted JSON write also corrupted the prior settings file and left memory advanced to an unsaved value. Failed settings writes currently surface as generic HTTP 500s.
Changes
OSErrors; never log the value being saved.Verification
Test-first reproduction of partial serialization: old file became a JSON fragment and memory became the unsaved locale. Delegated initial tests: 9 failed / 5 characterization passes before implementation. Parent added and observed failing concurrent-update and symlink regressions, then repaired both.
make typecheck: 31 source files clean.Limits
Linux offline tests simulate Windows-style replacement denial; native Windows behavior still needs CI/reporter verification. New settings files use the tempfile's private 0600 mode; existing modes are retained. Atomic replacement changes inode identity, so hard links/ownership across different service users are not preserved. No cross-process locking or parent-directory fsync/power-loss durability guarantee is added. The absolute local config path is intentionally included in the authenticated/loopback API diagnostic, as it already is in the local error logs. Read-only files remain read-only: no automatic chmod, deletion or ACL changes.
Related: ActivityWatch/activitywatch#1537. Keep that report open pending diagnosis; this hardening is not evidence that the reporter's permission issue is resolved.