Files
qbz/crates/qbz-integrations/Cargo.toml
T
vicrodh 857cb16e87 fix(mb): retry MusicBrainz 503s and transport failures behind a shared limiter
- Route every endpoint through a new send_with_retry: it waits on the rate
  limiter, GETs, logs the x-ratelimit budget, and on a 503/429 backs off the
  server's Retry-After (capped 8s) and retries, up to 3 attempts. get_artist_tags
  and get_recording_isrcs, which skipped status handling entirely, now go
  through it too.
- Also retry transient TRANSPORT failures (a hung connection to the request
  timeout, a drop or refusal). MusicBrainz under load hangs instead of returning
  503, which surfaced as "error sending request for url". Capped at 2 attempts
  with a 6s request timeout so a total failure is ~13s, not ~33s, while a hang
  that clears still recovers on the second try.
- Share ONE process-wide direct rate limiter across every client (core, the tag
  editor, remote metadata) so several clients on one public IP pace as one 1.1s
  stream instead of each pacing itself.
- Log MusicBrainz's x-ratelimit-limit/remaining/reset headers (debug on 2xx,
  warn on 429/503) as the only signal of whether the bucket was ours or MB's.

Tests: 503-then-200, a dropped connection, and shared-limiter serialization,
each red-to-green. Dev-only deps (tokio test features + rustls/aws-lc-rs to
install the crypto provider); no runtime dependency added.

cc
2026-09-10 13:23:53 -06:00

45 lines
1.2 KiB
TOML

[package]
name = "qbz-integrations"
version = "0.1.0"
edition = "2021"
description = "Third-party service integrations for QBZ (Last.fm, ListenBrainz, MusicBrainz)"
license = "MIT"
[dependencies]
# Async runtime
tokio = { version = "1", features = ["sync", "time"] }
# HTTP client
reqwest = { workspace = true, default-features = false, features = ["json", "query", "rustls-no-provider"] }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Logging
log = "0.4"
# Error handling
thiserror = "1"
# URL encoding for API queries
urlencoding = "2"
# Discord Rich Presence (now-listening activity). Same crate + version the
# Tauri build used; frontend-agnostic (IPC-only, no Tauri dependency).
discord-rich-presence = "1.1.0"
# SQLite for caching (optional, enabled by default)
rusqlite = { version = "0.40", features = ["bundled"], optional = true }
# Time handling for cache TTL
chrono = { version = "0.4", optional = true }
[dev-dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "io-util"] }
rustls = { version = "0.23", features = ["aws_lc_rs"] }
[features]
default = ["cache"]
cache = ["dep:rusqlite", "dep:chrono"]