Skip to content

fix(sync): log every delivery, not just the ones that went wrong - #69

Merged
davidboulay merged 1 commit into
mainfrom
fix/log-successful-sync-delivery
Jul 31, 2026
Merged

fix(sync): log every delivery, not just the ones that went wrong#69
davidboulay merged 1 commit into
mainfrom
fix/log-successful-sync-delivery

Conversation

@davidboulay

Copy link
Copy Markdown
Owner

The problem

sync.log gated its success line on attempt or (ip, port) != addrs[0] (text) and (ip, port) != addrs[0] (media). A send that landed on the first attempt to the primary mDNS address — the healthy path, i.e. nearly every send — wrote nothing. The log only ever recorded retries, address fallbacks and outright failures.

So a working sync and a dead one produce byte-identical logs, and the silence reads as absence of activity. In one debugging session that cost two wrong diagnoses: an empty log was taken as "no send was even attempted", which sent the investigation after _seen_has() echo-suppression and the swallowed exceptions around engine.broadcast_id(eid) in mac_app.on_change(). Every clip had in fact been delivered. netstat is what settled it — a fresh 192.168.1.60.<ephemeral> -> 192.168.1.17.47823 TIME_WAIT per copy, three for three.

The change

Both log lines are unconditional. Volume is already bounded: _log truncates sync.log to the last 256 KB once it passes 512 KB.

Regression guard

New case 6 in scripts/sync_delivery_test.py delivers to a single good address — attempt == 0, addrs[0], precisely the case that used to be silent — and asserts the line exists. Against the pre-fix sync.py it fails with:

AssertionError: a first-attempt delivery to the primary address must be logged, got []

Scope note: the guard covers the text path. The media guard was identical in shape and is removed alongside it, but streaming a blob isn't exercised by this test.

Self-tests stop polluting the real log

All three sync self-tests were writing into the live <data>/sync.log, and this change would have made them noisier — successes now log too. They now point sync._SYNC_LOG at a temp dir. Worth knowing when reading an existing log: delivered to macbookpro-1.home via 127.0.0.1:48051 followed by 127.0.0.1:9 refused is self-test residue, not traffic.

Verification

  • python -m compileall clippy scripts — OK
  • scripts/mac_selector_test.py — OK across 9 PyObjC classes in 32 sources
  • sync_selftest.py, sync_drift_test.py, sync_delivery_test.py — all pass
  • Real ~/.local/share/clippy/sync.log after a full suite run: 626 lines before, 626 after

🤖 Generated with Claude Code

sync.log gated its success line on `attempt or (ip, port) != addrs[0]`
(text) and `(ip, port) != addrs[0]` (media), so a send that landed on the
first try to the primary mDNS address wrote nothing at all. The log only
ever spoke up about retries, address fallbacks and failures.

That makes a healthy idle sync and a completely dead one look identical on
disk, and the silence actively invites the wrong reading: twice in one
debugging session an empty log was taken as "no send was even attempted",
sending the investigation after `_seen_has()` suppression and swallowed
exceptions in mac_app.on_change() — when in fact every clip was being
delivered. netstat showed the truth: a fresh
192.168.1.60.<ephemeral> -> 192.168.1.17.47823 TIME_WAIT per copy.

Both log lines are now unconditional. `_log` self-bounds sync.log at 512 KB
(truncating to the last 256 KB), so the extra volume is already capped.

Guarded by a new case 6 in scripts/sync_delivery_test.py: deliver to a
single good address — attempt 0, addrs[0], the exact case that used to be
silent — and assert the line is there. It fails on the old code with
`got []`. The text path is covered; the media guard was identical in shape
and removed alongside it, but streaming a blob is not exercised here.

The three sync self-tests now point _SYNC_LOG at a temp dir. They were
writing into the real <data>/sync.log, which this change would have made
noisier — the `delivered to macbookpro-1.home via 127.0.0.1:48051` pairs in
a live log are self-test residue, not traffic. Suite now leaves it
untouched (delta 0 lines).

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@davidboulay
davidboulay merged commit de8ba55 into main Jul 31, 2026
1 check passed
@davidboulay
davidboulay deleted the fix/log-successful-sync-delivery branch July 31, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant