Implement bounded transient database retries and accurate failure diagnostics #44

Closed
opened 2026-09-05 22:42:13 +00:00 by tophattedcat · 0 comments
Owner

Problem

SPEC.md section 11 requires bounded retries for transient database contention. Plugin state operations currently translate SQLite errors directly into failures; connection timeout waiting is not an operation-level retry policy. The sync lock-failure test expects immediate failure.

The broad exception handler in sync also reports write failures as a playlist database that “could not be opened,” potentially attributing a beets write failure to the wrong store.

Proposed change

Retry known transient database failures at appropriate idempotent transaction boundaries. Preserve the original cause and identify the affected store and operation in user-facing diagnostics. Do not retry schema, constraint, permission, invalid-data, or persistent I/O failures. Account for any retries already provided by upstream stores.

Acceptance criteria

  • A transient busy/locked failure followed by success completes within a bounded retry budget.
  • Exhaustion fails non-zero; permanent failures are attempted once.
  • Retries do not duplicate memberships or lose intended item updates.
  • Failed full sync skips global pruning.
  • Read/open/write failures identify the correct operation and store.
  • Add network-free regression tests with controlled failures/backoff.

References: beetsplug/appleplaylists/state.py:111-161, sync.py:203-210, tests/test_sync.py:460. Audit finding 3 (medium).

## Problem SPEC.md section 11 requires bounded retries for transient database contention. Plugin state operations currently translate SQLite errors directly into failures; connection timeout waiting is not an operation-level retry policy. The sync lock-failure test expects immediate failure. The broad exception handler in sync also reports write failures as a playlist database that “could not be opened,” potentially attributing a beets write failure to the wrong store. ## Proposed change Retry known transient database failures at appropriate idempotent transaction boundaries. Preserve the original cause and identify the affected store and operation in user-facing diagnostics. Do not retry schema, constraint, permission, invalid-data, or persistent I/O failures. Account for any retries already provided by upstream stores. ## Acceptance criteria - A transient busy/locked failure followed by success completes within a bounded retry budget. - Exhaustion fails non-zero; permanent failures are attempted once. - Retries do not duplicate memberships or lose intended item updates. - Failed full sync skips global pruning. - Read/open/write failures identify the correct operation and store. - Add network-free regression tests with controlled failures/backoff. References: `beetsplug/appleplaylists/state.py:111-161`, `sync.py:203-210`, `tests/test_sync.py:460`. Audit finding 3 (medium).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coop/beets-appleplaylists#44
No description provided.