mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
cbd5f56778
Read selection was positional: prefer any open remote read, else a cached book-level id, else the first read returned, while the primary attempt was re-derived each sync from book dates. The two could disagree, assigning one Hardcover read to two attempts and violating reading_attempts_external_uidx, which aborted the sync and persisted the failure. Treat reading_attempts.external_id as the mapping of record: an attempt keeps the read it owns, an unlinked attempt adopts only an unclaimed read and claims it locally before the remote write, and a fresh read is minted when nothing is adoptable. Never merge or delete attempts to resolve a conflict, and keep soft-deleted ids reserved so importExternalRead tombstones still hold. Also skip the link write when an attempt already owns its read, and map the aggregated attempt timestamp to a Date so change detection stops comparing a driver string against lastSyncedAt. Closes #907