mirror of
https://github.com/seerr-team/seerr.git
synced 2026-05-24 08:49:59 -04:00
fix(availability-sync): add caching for expisode exist checks for plex/jellyfin
This commit is contained in:
@@ -21,9 +21,11 @@ class AvailabilitySync {
|
||||
public running = false;
|
||||
private plexClient: PlexAPI;
|
||||
private plexSeasonsCache: Record<string, PlexMetadata[]>;
|
||||
private plexEpisodeExistsCache: Record<string, boolean>;
|
||||
|
||||
private jellyfinClient: JellyfinAPI;
|
||||
private jellyfinSeasonsCache: Record<string, JellyfinLibraryItem[]>;
|
||||
private jellyfinEpisodeExistsCache: Record<string, boolean>;
|
||||
|
||||
private sonarrSeasonsCache: Record<string, SonarrSeason[]>;
|
||||
private radarrServers: RadarrSettings[];
|
||||
@@ -34,7 +36,9 @@ class AvailabilitySync {
|
||||
const mediaServerType = getSettings().main.mediaServerType;
|
||||
this.running = true;
|
||||
this.plexSeasonsCache = {};
|
||||
this.plexEpisodeExistsCache = {};
|
||||
this.jellyfinSeasonsCache = {};
|
||||
this.jellyfinEpisodeExistsCache = {};
|
||||
this.sonarrSeasonsCache = {};
|
||||
this.radarrServers = settings.radarr.filter((server) => server.syncEnabled);
|
||||
this.sonarrServers = settings.sonarr.filter((server) => server.syncEnabled);
|
||||
@@ -939,7 +943,6 @@ class AvailabilitySync {
|
||||
const ratingKey4k = media.ratingKey4k;
|
||||
let seasonExistsInPlex = false;
|
||||
|
||||
// Check each plex instance to see if the season exists
|
||||
let plexSeasons: PlexMetadata[] | undefined;
|
||||
|
||||
if (ratingKey && !is4k) {
|
||||
@@ -955,18 +958,27 @@ class AvailabilitySync {
|
||||
);
|
||||
|
||||
if (seasonMeta) {
|
||||
// Season metadata exists, but verify it has actual episode files.
|
||||
// This is to ensure we don't keep seasons marked as available
|
||||
// when all episode files have been removed in Plex.
|
||||
try {
|
||||
const episodes = await this.plexClient?.getChildrenMetadata(
|
||||
seasonMeta.ratingKey
|
||||
);
|
||||
const cacheKey = seasonMeta.ratingKey;
|
||||
|
||||
seasonExistsInPlex = episodes?.length > 0;
|
||||
} catch {
|
||||
// If we can't fetch episodes, assume the season exists to avoid false removal
|
||||
seasonExistsInPlex = true;
|
||||
if (cacheKey in this.plexEpisodeExistsCache) {
|
||||
seasonExistsInPlex = this.plexEpisodeExistsCache[cacheKey];
|
||||
} else {
|
||||
try {
|
||||
// Season metadata exists, but we need to verify it has actual
|
||||
// episode files. Plex can keep empty season entries.
|
||||
const episodes = await this.plexClient?.getChildrenMetadata(
|
||||
seasonMeta.ratingKey
|
||||
);
|
||||
|
||||
seasonExistsInPlex =
|
||||
episodes?.some((episode) => episode.Media?.length > 0) ?? false;
|
||||
} catch {
|
||||
// If we can't fetch episodes, assume the season exists
|
||||
// to avoid false removal
|
||||
seasonExistsInPlex = true;
|
||||
}
|
||||
|
||||
this.plexEpisodeExistsCache[cacheKey] = seasonExistsInPlex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,7 +1080,6 @@ class AvailabilitySync {
|
||||
const ratingKey4k = media.jellyfinMediaId4k;
|
||||
let seasonExistsInJellyfin = false;
|
||||
|
||||
// Check each jellyfin instance to see if the season exists
|
||||
let jellyfinSeasons: JellyfinLibraryItem[] | undefined;
|
||||
|
||||
if (ratingKey && !is4k) {
|
||||
@@ -1084,22 +1095,32 @@ class AvailabilitySync {
|
||||
);
|
||||
|
||||
if (seasonMeta) {
|
||||
// Season metadata exists, but we need to verify it has actual episode files.
|
||||
// Sometimes Jellyfin keeps season entries even after all episodes are deleted.
|
||||
// getEpisodes already filters out virtual episodes.
|
||||
const seriesId = is4k ? ratingKey4k : ratingKey;
|
||||
|
||||
if (seriesId) {
|
||||
try {
|
||||
const episodes = await this.jellyfinClient.getEpisodes(
|
||||
seriesId,
|
||||
seasonMeta.Id
|
||||
);
|
||||
const cacheKey = `${seriesId}-${seasonMeta.Id}`;
|
||||
|
||||
seasonExistsInJellyfin = episodes.length > 0;
|
||||
} catch {
|
||||
// If we can't fetch episodes, assume the season exists to avoid false removal
|
||||
seasonExistsInJellyfin = true;
|
||||
if (cacheKey in this.jellyfinEpisodeExistsCache) {
|
||||
seasonExistsInJellyfin = this.jellyfinEpisodeExistsCache[cacheKey];
|
||||
} else {
|
||||
try {
|
||||
// Season metadata exists, but we need to verify it has actual
|
||||
// episode files. Jellyfin keeps season entries even after all
|
||||
// episodes are deleted. getEpisodes already filters out
|
||||
// virtual episodes.
|
||||
const episodes = await this.jellyfinClient.getEpisodes(
|
||||
seriesId,
|
||||
seasonMeta.Id
|
||||
);
|
||||
|
||||
seasonExistsInJellyfin = episodes.length > 0;
|
||||
} catch {
|
||||
// If we can't fetch episodes, assume the season exists
|
||||
// to avoid false removal
|
||||
seasonExistsInJellyfin = true;
|
||||
}
|
||||
|
||||
this.jellyfinEpisodeExistsCache[cacheKey] = seasonExistsInJellyfin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user