* fix(watchsync): respect MDBList rate limits and defer syncs on 429
MDBList caps API usage at 1,000 requests/day on the free tier, and a
large-library first sync (paginated watched/watchlist fetches plus
exports chunked at 100 items per POST) could blow through it. A 429 was
treated as a generic failure: every pending chunk was marked failed and
the next scheduled run replayed the whole sync into the same limit.
- Pace MDBList requests at ~1/s per API key and retry 429s with a short
Retry-After in place; longer waits surface a typed RateLimitedError.
- Abort the remaining sync flows on the first rate-limited flow and
persist rate_limited_until on the connection; scheduled syncs skip it
until the deferral passes and manual sync returns a proper cooldown.
- Leave rate-limited exports pending instead of marking them failed so
the next run resumes where it stopped.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(watchsync): address rate-limit review feedback
- Floor RateLimitedError.RetryAfter to the default deferral when in-place
retries are exhausted, so untrustworthy short Retry-After hints can't
produce a seconds-long deferral that walks straight back into the limit.
- Stamp rate_limited_until on every connection bound to the same provider
account (the quota belongs to the API key, not the profile), and re-read
connections mid-batch in SyncDueConnections so siblings deferred after
the snapshot are skipped.
- Filter deferred connections out of the live dispatch queries
(local watch events, list events, scrobbles) so real-time exports stop
burning quota during a cooldown.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>