/
/
# What does this implement/fix? Tracks that ended up in the library twice, once per music provider, stayed that way forever. The recent matching fixes only prevent *new* duplicates: when a provider syncs again, an existing track is found straight away by its own provider mapping, so the cross-provider comparison never runs a second time and the leftovers are never cleaned up. This adds a small hourly maintenance pass that repairs them, merging the two rows into one through the existing safe merge path, so albums, artists, play counts and listening history are moved across before the duplicate row goes away. To be sure it only merges genuine duplicates, a pair has to agree on quite a lot: same title, a shared artist, near-equal length, and both providers listing the track on the same album at the same position. Versions have to match too, so remasters, remixes, radio edits and re-recordings are left alone. - New hourly "Reconcile duplicate tracks" background task, 100 candidate pairs per run, picking up where it left off after a restart - Only merges tracks from different providers; two rows from the same provider are never touched - Album editions are compared too, so an original and its remaster stay separate, while quality labels like Hi-Res are ignored - Waits until any running library sync has finished before judging anything - The row with the most provider mappings is the one that stays **Related issue (if applicable):** - https://github.com/music-assistant/support/issues/4455 ## Types of changes <!-- Tick exactly one box. CI (.github/workflows/pr-labels.yaml) derives the label from the ticked box and applies it automatically; the release-notes generator uses that same label to slot this change into the next release notes. --> - [x] Bugfix (non-breaking change which fixes an issue) — `bugfix` - [ ] New feature (non-breaking change which adds functionality) — `new-feature` - [ ] Enhancement to an existing feature — `enhancement` - [ ] New music/player/metadata/plugin provider — `new-provider` - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) — `breaking-change` - [ ] Refactor (no behaviour change) — `refactor` - [ ] Documentation only — `documentation` - [ ] Maintenance / chore — `maintenance` - [ ] CI / workflow change — `ci` - [ ] Dependencies bump — `dependencies` ## Checklist - [x] The code change is tested and works locally. - [x] `pre-commit run --all-files` passes. - [x] `pytest` passes, and tests have been added/updated under `tests/` where applicable. - [ ] For changes to shared models, the companion PR in `music-assistant/models` is linked. - [ ] For changes affecting the UI, the companion PR in `music-assistant/frontend` is linked. - [x] I have read and complied with the project's [AI Policy](https://github.com/music-assistant/.github/blob/main/AI_POLICY.md) for any AI-assisted contributions. - [ ] I have [raised a PR against the documentation repository](https://github.com/music-assistant/music-assistant.io/blob/main/CONTRIBUTING.md) targeting the main or beta branch as appropriate.