fix(aw-sync): open peer databases read-only; skip version mismatch - #700
Conversation
Pull used Datastore::new on files this device does not own, which flipped journal_mode to WAL (creating -wal/-shm sidecars), ran migrations, and aborted the whole pass on user_version skew. Open peers with file:?mode=ro&immutable=1, never migrate, and skip + warn when user_version != NEWEST. Own staging still uses the read-write constructor. ActivityWatch#693 v0.14.0 slice (the full tolerant reader for old indexes is not in this PR). Git-Session-Id: 3a97ef00-28f8-50e5-99de-b20a862e44e0
Review guide (auto-posted)Structured warm-up for reviewers — what changed, what to run, where to look. Key files
Suggested verification
Known risks / watch points
Suggested review focus
Generated by |
|
@TimeToBuildBob This does what step 4 asked. Verified: peer opens are Two notes, neither blocking: 1. The residual per-peer abort is not this PR's job — but it should be named. 2. Please document what Also for Erik's awareness: this touches Ready to merge when CI is green. Queue position: after #698, and it does not need to wait for #697. |
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #700 +/- ##
==========================================
+ Coverage 70.81% 79.90% +9.09%
==========================================
Files 51 72 +21
Lines 2916 6913 +3997
==========================================
+ Hits 2065 5524 +3459
- Misses 851 1389 +538 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…y opens Peer workers used BEGIN IMMEDIATE, which is a write lock. Deferred is the correct read-only behavior. Doc-comment what immutable=1 gives up so it is not dropped later to "see the WAL". Git-Session-Id: ca842b73-e7ac-505f-b5bd-1136e4137c8d
|
Documented on Also switched the read-only worker to Left as named: unexpected open errors still abort the pass until #697's per-peer Still queued after #698. |
|
@TimeToBuildBob Assessed Greptile's three P1s. One is a false positive I verified empirically, one is a doc comment, one is a real two-line fix. Two small changes and this merges. P1 "Read-only workers hang" — false positive, but the fragility is realGreptile's reasoning is sound on its face: It does not fail. I ran the new test on this head with a 150 s timeout: That test exercises real Why it still needs a one-line change: that safety depends on let behavior = if read_only { TransactionBehavior::Deferred } else { TransactionBehavior::Immediate };P1 "Mutable files marked immutable" — keep
|
\\server\share\peer.db was becoming file://server/share/... which parses `server` as the URI authority. Detect Windows path shapes from the path (not cfg!(windows)) and use file:////server/share/... Document the in-place-rewrite caveat on immutable=1. ActivityWatch#700 Git-Session-Id: fc3a102a-6378-50f2-828f-8b5e6f9b5df9
|
@ErikBjare The three P1s as you assessed, now on
Residual unexpected-open abort is still #697's Retriggering Greptile on this head. |
|
@greptileai review |
…eadonly URI A bare backslash is a valid POSIX filename character. sqlite_readonly_uri() was rewriting it to a forward slash whenever any backslash was present, corrupting a POSIX path that happens to contain one and potentially opening the wrong file or failing to open at all. Only classify a path as Windows when it has a drive letter or a UNC prefix. Git-Session-Id: e82d
|
Greptile's fourth P1 on re-review was also real: Fixed on |
|
@greptileai review |
🤖 AI code reviewSafe to merge — 1 P1 disposed (rejected)Updated after inline dispositions on finding threads — this is the current state; the verdict below is frozen at review time and is kept as the historical record of that pass. Finding disposition
This PR adds a read-only datastore open path for aw-sync peer databases. It introduces DatastoreMethod::FileReadOnly, a sqlite_readonly_uri helper that builds a file: URI with mode=ro&immutable=1, and Datastore::open_read_only which probes user_version and returns OldDbVersion on mismatch. aw-sync's sync_run and list_buckets now use open_peer_datastore to skip version-mismatched peers instead of aborting. The worker skips WAL/synchronous pragmas and uses Deferred transactions for read-only connections. Needs a look — P2 onlyConfidence 4/5 1 finding ·
|
| commit | score | findings | engine | when |
|---|---|---|---|---|
d260b1683f53 |
4/5 | 4 | llm | 2026-09-16 09:15 UTC |
955c5161fbb8 |
3/5 | 3 | llm | 2026-09-16 09:57 UTC |
Reviewed 3c1eeb10d394 · openrouter/deepseek/deepseek-v4-flash-0731 · llm engine · 123s · about this reviewer
Maintainer commands
@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.
|
CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
|
@TimeToBuildBob Required — gate the backslash rewrite on platform, not path shape ( Then merge on green. Not rebased on current master but |
A backslash is a legal POSIX filename character. Path-shape detection still ran the rewrite/UNC branches on Linux, so a peer path containing `\` could target a different file or abort the pass. Wrap drive-letter and UNC normalisation in cfg!(windows); POSIX paths pass through. ActivityWatch#700 Git-Session-Id: d65e2e09-0f68-5f08-b9c2-226c2d762c15
|
@ErikBjare Done on Cannot self-merge here (pull-only on ActivityWatch/aw-server-rust). Squash when green — #698 is already merged, so this is unblocked on queue. Residual unexpected-open abort remains #697. |
|
@greptileai review |
|
Verified on |
|
Ack the 10:14 verification on Leftover AI-review P2 (probe/open TOCTOU, |
v0.14.0 slice of #693, as sequenced on ActivityWatch/activitywatch#1445. Independent of #685.
Problem
sync_runopened every peer db withDatastore::new, which is a write:journal_mode=WALcreates-wal/-shmsidecars in a folder this device does not ownDatastoreInstance::new(&conn, true)migratesuser_versionon files it does not ownuser_version != 6) aborted the whole passAndroid and
aw-sync syncalready pull today, so this is live, not latent on the daemon switch.Fix
Datastore::open_read_onlyopensfile:…?mode=ro&immutable=1, skips WAL/synchronous pragmas, and never migratesuser_version != NEWEST_DB_VERSIONreturnsOldDbVersion; aw-sync skips that peer with a warning and keeps walkingcreate_datastore/setup_local_remote) is unchangedNot in this PR: a tolerant reader for old index names (the full #693 work item). v4 peers are skipped, not imported.
Tests
test_read_only_open_does_not_create_wal_sidecarstest_read_only_open_skips_old_user_version