fix: never discard a play that has not been submitted
Build and publish container / build (pull_request) Successful in 5m11s

Setting the logs aside after a successful submission threw away more than it
had submitted. A play of a track missing from the mirror -- not yet copied, or
its tags unreadable -- was counted as unresolved and then carried off with the
rest, with nothing to retry it. The play happened and was lost.

Two obligations now, kept separate. The original log is renamed rather than
deleted, so a mistake here cannot destroy the record. And every play that was
not submitted is written back into a live log, so the next run attempts it
again: the unmatched ones, and anything in a batch that failed.

Submission is recorded batch by batch as each is accepted, so a failure partway
through knows exactly what got through. The remainder is written back and
nothing is sent twice. When nothing at all is accepted the logs are left
untouched.

Skips and clockless entries are deliberately not retained. Neither can ever be
submitted, so keeping them would mean reprocessing them for ever, and the
untouched original holds them regardless.

Also fixes a way to lose the lot: read_tags caught OSError and ValueError, but
ffprobe failing raises CalledProcessError, which is neither. A single unreadable
file aborted the whole submission rather than costing one unidentified play.
This commit is contained in:
Emma Thorpe
2026-08-26 18:32:05 +01:00
parent f324b1b720
commit 374a17474f
3 changed files with 273 additions and 39 deletions
+23 -2
View File
@@ -309,8 +309,29 @@ real-time clock Rockbox writes `/.scrobbler-timeless.log` with every timestamp
set to zero; those are counted and reported but never submitted, because
scrobbling them would mean inventing when they happened.
The log is renamed rather than deleted once accepted. If Last.fm quietly
dropped something, the evidence is still on the device.
### Nothing played is thrown away
Two separate obligations, because a play that happened and never reached
Last.fm is gone for good.
**The original is renamed, never deleted.** If Last.fm quietly dropped
something, the evidence is still on the device as `playback.log.<ts>.submitted`.
**Anything not submitted is written back** into a live log for the next run:
| Outcome | What happens to it |
| ------------------------------ | ----------------------------------------- |
| Accepted by Last.fm | dropped from the live log |
| Not in the mirror yet | written back, tried again next run |
| In a batch that failed | written back, tried again next run |
| Nothing accepted at all | logs left completely untouched |
| A skip, or no usable timestamp | not retained — neither can ever be submitted, and the original still has it |
The batch boundary matters: submission is recorded as each batch is accepted,
so a failure partway through knows exactly what got through and writes back
only the remainder. No duplicates, no losses.
A file `ffprobe` cannot read costs one unidentified play, not the run.
`check_fat32.py` reports paths a FAT32 device will not accept — reserved
characters, trailing dots and spaces, over-long components and paths, and names