Skip to content

feat(metadata): add ID validation and retry path for metadata refresh#2594

Merged
enoch85 merged 1 commit into
developmentfrom
feat/metadata-refresh-action
Apr 2, 2026
Merged

feat(metadata): add ID validation and retry path for metadata refresh#2594
enoch85 merged 1 commit into
developmentfrom
feat/metadata-refresh-action

Conversation

@enoch85

@enoch85 enoch85 commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds media-server-id.utils.ts with heuristic ID classification (isLikelyPlexId, isLikelyJellyfinId, isJellyfinEmptyGuid, isForeignServerId, shouldRefreshMetadataItemId) to identify and skip IDs that belong to the wrong server type before queuing metadata refresh requests. All checks are implemented without regex to avoid ReDoS.
  • Filters foreign-server IDs (e.g. Jellyfin UUIDs stored against a Plex instance, or all-digit Plex IDs stored against a Jellyfin instance) and Jellyfin empty GUIDs (00000000...) with a logged warning rather than silently failing.
  • Adds a GET-on-failure retry path in MetadataSettingsService.refreshMediaServerItem for manual refresh triggers: on first failure, calls getMetadata to retrieve a verified (possibly corrected) item ID and retries once. This covers Jellyfin Guid can't be empty corruption scenarios where the stored ID has drifted from the server's current ID.
  • Retry path is opt-in (retryFailedItemsWithMetadataLookup); automatic scheduled refreshes use the cheaper no-GET path.
  • Adds blank-ID guards to both Jellyfin and Plex adapter refreshItemMetadata methods. Demotes adapter-level refresh failure logging from error to warn to avoid false alarms when the service-layer retry succeeds.

Test plan

  • media-server-id.utils.spec.ts — 25 unit tests covering all exported functions, both server types, edge cases (empty GUID both forms, dashes at wrong positions, blank/whitespace)
  • metadata-settings.service.spec.ts — 10 integration tests: overlap prevention, batch concurrency, ID filtering for Jellyfin and Plex, retry disabled/same-ID/corrected-ID/lookup-throws/blank-ID/retry-fails paths
  • jellyfin-adapter.service.spec.ts — refresh queues valid Jellyfin item IDs
  • plex-adapter.service.spec.ts — existing tests confirm foreign-ID filter wired up
  • Run yarn workspace @maintainerr/server test and confirm all 110 tests pass

Introduces media-server-id.utils with heuristic ID classification to
skip foreign-server IDs (e.g. Jellyfin UUIDs stored against a Plex
instance) before queuing metadata refresh requests. Adds a GET-on-failure
retry path in MetadataSettingsService for manual refreshes: on first
failure, looks up the item to get a verified (possibly corrected) ID and
retries once, covering Jellyfin 'Guid can't be empty' corruption scenarios.
@enoch85 enoch85 merged commit 115fd8e into development Apr 2, 2026
13 checks passed
@enoch85 enoch85 deleted the feat/metadata-refresh-action branch April 2, 2026 18:31
maintainerr-automation Bot added a commit that referenced this pull request Apr 3, 2026
* fix(server): Use shared watch state for isWatched and Plex viewCount (#2570)

* Metadata provider abstraction layer with TVDB support (#2573)

* fix: register tvdb cache in CacheManager

* build(deps-dev): bump the nestjs group with 2 updates (#2575)

Bumps the nestjs group with 2 updates: [@nestjs/cli](https://github.com/nestjs/nest-cli) and [@nestjs/schematics](https://github.com/nestjs/schematics).


Updates `@nestjs/cli` from 11.0.16 to 11.0.17
- [Release notes](https://github.com/nestjs/nest-cli/releases)
- [Commits](nestjs/nest-cli@11.0.16...11.0.17)

Updates `@nestjs/schematics` from 11.0.9 to 11.0.10
- [Release notes](https://github.com/nestjs/schematics/releases)
- [Commits](nestjs/schematics@11.0.9...11.0.10)

---
updated-dependencies:
- dependency-name: "@nestjs/cli"
  dependency-version: 11.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: nestjs
- dependency-name: "@nestjs/schematics"
  dependency-version: 11.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: nestjs
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump axios from 1.13.6 to 1.14.0 (#2576)

Bumps [axios](https://github.com/axios/axios) from 1.13.6 to 1.14.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.13.6...v1.14.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump knip from 6.0.6 to 6.1.1 (#2578)

Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 6.0.6 to 6.1.1.
- [Release notes](https://github.com/webpro-nl/knip/releases)
- [Commits](https://github.com/webpro-nl/knip/commits/knip@6.1.1/packages/knip)

---
updated-dependencies:
- dependency-name: knip
  dependency-version: 6.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump @tanstack/eslint-plugin-query (#2579)

Bumps [@tanstack/eslint-plugin-query](https://github.com/TanStack/query/tree/HEAD/packages/eslint-plugin-query) from 5.91.4 to 5.96.0.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/eslint-plugin-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/eslint-plugin-query@5.96.0/packages/eslint-plugin-query)

---
updated-dependencies:
- dependency-name: "@tanstack/eslint-plugin-query"
  dependency-version: 5.96.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(ui): smooth settings refresh and stream warnings + tune flickering and loadingspinner (#2574)

* build(deps): bump react-router-dom from 7.13.1 to 7.13.2 (#2584)

Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 7.13.1 to 7.13.2.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.13.2/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-version: 7.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump ts-jest from 29.4.6 to 29.4.9 (#2583)

Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 29.4.6 to 29.4.9.
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](kulshekhar/ts-jest@v29.4.6...v29.4.9)

---
updated-dependencies:
- dependency-name: ts-jest
  dependency-version: 29.4.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump @typescript-eslint/eslint-plugin (#2585)

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.57.2 to 8.58.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.58.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(ui): stabilize library switching and add media sorting (#2586)

* build(deps): bump lodash-es from 4.17.23 to 4.18.1 (#2587)

Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-version: 4.18.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat(metadata): add per-provider metadata refresh action

Adds a "Refresh metadata" button to each provider card in Metadata
Settings. Clicking it:
1. Tests the provider connection as a safety net before touching cache
2. Flushes only that provider's local NodeCache
3. Fires batched refreshItemMetadata calls to Plex/Jellyfin for all
   collection items linked to that provider (fire-and-forget)

Button label is context-aware ("Save to refresh", "Configure to
refresh") and disabled while unsaved changes are pending. Inline
feedback reuses the shared useSettingsFeedback pattern. A server-side
in-progress guard prevents concurrent refreshes of the same provider.

* fix(ui): make overview title sort explicit (#2589)

* build(deps): bump @tanstack/react-query from 5.91.3 to 5.96.1 (#2590)

Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.91.3 to 5.96.1.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.96.1/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.96.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump @tanstack/eslint-plugin-query (#2591)

Bumps [@tanstack/eslint-plugin-query](https://github.com/TanStack/query/tree/HEAD/packages/eslint-plugin-query) from 5.96.0 to 5.96.1.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/eslint-plugin-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/eslint-plugin-query@5.96.1/packages/eslint-plugin-query)

---
updated-dependencies:
- dependency-name: "@tanstack/eslint-plugin-query"
  dependency-version: 5.96.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump lodash from 4.17.23 to 4.18.1 (#2592)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.18.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat(metadata): add ID validation and retry path for metadata refresh (#2594)

Introduces media-server-id.utils with heuristic ID classification to
skip foreign-server IDs (e.g. Jellyfin UUIDs stored against a Plex
instance) before queuing metadata refresh requests. Adds a GET-on-failure
retry path in MetadataSettingsService for manual refreshes: on first
failure, looks up the item to get a verified (possibly corrected) ID and
retries once, covering Jellyfin 'Guid can't be empty' corruption scenarios.

* fix: stabilize metadata sourcing and settings feedback flows (#2595)

* fix(ui): use active metadata provider in media modal

* chore(server): clean metadata lint warnings

* change tvdb link

* fix: align settings feedback and persist github cache

* fix(ui): align metadata test button text

* Update API key link in Metadata component

* fix: delete Tautulli config on media server switch to Jellyfin (#2597)

* build(deps): bump the nestjs group with 5 updates (#2598)

Bumps the nestjs group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@nestjs/common](https://github.com/nestjs/nest/tree/HEAD/packages/common) | `11.1.17` | `11.1.18` |
| [@nestjs/core](https://github.com/nestjs/nest/tree/HEAD/packages/core) | `11.1.17` | `11.1.18` |
| [@nestjs/platform-express](https://github.com/nestjs/nest/tree/HEAD/packages/platform-express) | `11.1.17` | `11.1.18` |
| [@nestjs/typeorm](https://github.com/nestjs/typeorm) | `11.0.0` | `11.0.1` |
| [@nestjs/testing](https://github.com/nestjs/nest/tree/HEAD/packages/testing) | `11.1.17` | `11.1.18` |


Updates `@nestjs/common` from 11.1.17 to 11.1.18
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.18/packages/common)

Updates `@nestjs/core` from 11.1.17 to 11.1.18
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.18/packages/core)

Updates `@nestjs/platform-express` from 11.1.17 to 11.1.18
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.18/packages/platform-express)

Updates `@nestjs/typeorm` from 11.0.0 to 11.0.1
- [Release notes](https://github.com/nestjs/typeorm/releases)
- [Commits](nestjs/typeorm@11.0.0...11.0.1)

Updates `@nestjs/testing` from 11.1.17 to 11.1.18
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.18/packages/testing)

---
updated-dependencies:
- dependency-name: "@nestjs/common"
  dependency-version: 11.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nestjs
- dependency-name: "@nestjs/core"
  dependency-version: 11.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nestjs
- dependency-name: "@nestjs/platform-express"
  dependency-version: 11.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nestjs
- dependency-name: "@nestjs/typeorm"
  dependency-version: 11.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nestjs
- dependency-name: "@nestjs/testing"
  dependency-version: 11.1.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: nestjs
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump react-hook-form from 7.72.0 to 7.72.1 (#2599)

Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.72.0 to 7.72.1.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](react-hook-form/react-hook-form@v7.72.0...v7.72.1)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-version: 7.72.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump @tanstack/react-query from 5.96.1 to 5.96.2 (#2600)

Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.96.1 to 5.96.2.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.96.2/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.96.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps-dev): bump @tanstack/eslint-plugin-query (#2601)

Bumps [@tanstack/eslint-plugin-query](https://github.com/TanStack/query/tree/HEAD/packages/eslint-plugin-query) from 5.96.1 to 5.96.2.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/eslint-plugin-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/eslint-plugin-query@5.96.2/packages/eslint-plugin-query)

---
updated-dependencies:
- dependency-name: "@tanstack/eslint-plugin-query"
  dependency-version: 5.96.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: wortmanb <744697+wortmanb@users.noreply.github.com>
Co-authored-by: enoch85 <mailto@danielhansson.nu>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Javiink <43996484+Javiink@users.noreply.github.com>
@maintainerr-automation

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.4.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant