fix(availability-sync): detect deleted seasons when media server retains empty season metadata#2850
fix(availability-sync): detect deleted seasons when media server retains empty season metadata#2850fallenbagel wants to merge 4 commits intodevelopfrom
Conversation
📝 WalkthroughWalkthroughAdds per-sync caches and per-season episode checks for Plex and Jellyfin in availability sync (with safe "assume exists" fallback on fetch errors) and introduces a comprehensive test suite that exercises Plex/Jellyfin/Sonarr scenarios for season deletion and status transitions. Changes
Sequence Diagram(s)sequenceDiagram
participant Sync as AvailabilitySync
participant MS as Media Server (Plex / Jellyfin)
participant DB as Database
Sync->>DB: Load shows & seasons with metadata refs
loop for each season
Sync->>MS: Fetch season metadata
alt metadata missing
MS-->>Sync: Not found
Sync->>DB: Mark season DELETED
else metadata found
Sync->>MS: Fetch season's episodes/children
alt episodes found (non-empty)
MS-->>Sync: Episode list (non-empty)
Sync->>DB: Mark season AVAILABLE
else episodes empty
MS-->>Sync: Empty list
Sync->>DB: Mark season DELETED
else fetch error
MS-->>Sync: Error
Sync->>DB: Mark season AVAILABLE (safe fallback)
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
server/lib/availabilitySync.test.ts (1)
227-241: Nitpick: Episode type should be'episode'not'movie'.The
typefield is set to'movie'for what represents episode data. While this doesn't affect the current tests (since onlylengthis checked), it's semantically incorrect and could cause confusion or issues if future tests need to validate episode types.🔧 Suggested fix
function fakePlexEpisodes(count: number): PlexMetadata[] { return Array.from({ length: count }, (_, i) => ({ ratingKey: `ep-${i}`, guid: `plex://episode/ep-${i}`, - type: 'movie' as const, + type: 'episode' as const, title: `Episode ${i + 1}`, Guid: [], index: i + 1, leafCount: 0, viewedLeafCount: 0, addedAt: 0, updatedAt: 0, Media: [], })); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@server/lib/availabilitySync.test.ts` around lines 227 - 241, The fakePlexEpisodes helper creates PlexMetadata items with type set incorrectly to 'movie'; update the type field in fakePlexEpisodes (the object returned in the Array.from) from 'movie' to 'episode' (and adjust the literal/type assertion if present) so the fake episode fixtures correctly reflect episode metadata for future tests that inspect type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@server/lib/availabilitySync.test.ts`:
- Around line 227-241: The fakePlexEpisodes helper creates PlexMetadata items
with type set incorrectly to 'movie'; update the type field in fakePlexEpisodes
(the object returned in the Array.from) from 'movie' to 'episode' (and adjust
the literal/type assertion if present) so the fake episode fixtures correctly
reflect episode metadata for future tests that inspect type.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2c245b3d-3f42-498c-b7b2-1adbdd5e7143
📒 Files selected for processing (2)
server/lib/availabilitySync.test.tsserver/lib/availabilitySync.ts
There was a problem hiding this comment.
Pull request overview
Fixes the availability sync job incorrectly keeping TV seasons marked AVAILABLE when the media server returns season metadata despite all episode files being removed, preventing users from re-requesting those seasons.
Changes:
- Update Plex season existence detection to verify a season has episodes before treating it as present.
- Update Jellyfin season existence detection to verify a season has at least one non-virtual episode before treating it as present.
- Add a comprehensive unit test suite covering Jellyfin/Plex deleted-season scenarios and safe fallbacks on API failures.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| server/lib/availabilitySync.ts | Adds episode-level existence checks for Plex/Jellyfin seasons to avoid stale AVAILABLE seasons after episode deletion. |
| server/lib/availabilitySync.test.ts | Adds unit tests validating deleted-season detection and error fallback behavior for both Jellyfin and Plex. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…or shows (Jellyfin/Plex)
…including Media attributes
04a1bcd to
47dabcb
Compare
Description
The availability sync was not detecting deleted seasons on Jellyfin
(and potentially Plex), causing them to stay marked as
AVAILABLEevenafter all episode files were removed from the media server. Users were
unable to re-request these seasons.
The issue was that Jellyfin's
/Shows/{id}/Seasonsendpoint sometimes returnedseason metadata entries even when every episode in that season has been
deleted. The season existence check only looked for a matching season
metadata entry, so it always returned true for every season the media
server knew about, regardless of whether any files actually existed.
This overrode the correctly computed "not available" state from the
filtered seasons map, preventing the season updater from ever firing.
Debug logging on a similar scenario confirmed this for a Show instance (TMDB 1408):
Jellyfin returned all 9 season entries, Sonarr correctly reported only
season 6, but the Jellyfin result overwrote everything in the final
seasons map.
The fix adds an episode-level check in both
seasonExistsInJellyfinand
seasonExistsInPlex. After finding a season metadata entry, thesync now fetches the season's episodes and confirms at least one
non-virtual episode exists before marking the season as available.
On API error, it defaults to assuming the season exists to avoid
false removal.
How Has This Been Tested?
Screenshots / Logs (if applicable)
Checklist:
pnpm buildpnpm i18n:extractSummary by CodeRabbit
Bug Fixes
Tests