Summary
getWatchHistory() caches its processed results to avoid repeated per-user API calls across rule runs. getItemFavoritedBy() (#2393) and getTotalPlayCount() use the same pattern — iterating all users via getItemUserData() in batches — but neither caches their results.
For a rule group scanning N items with M users, each uncached method adds N × M API calls per rule run.
Why per-method caching (not a shared getItemUserData cache)
All three methods call getItemUserData() internally, so caching at that level seems appealing. However, downstream consumers of getWatchHistory() depend on the processed WatchRecord[] format — Date objects parsed from ISO strings, filtering by Played: true, and defaults applied via JellyfinMapper.toWatchRecord(). A raw getItemUserData() cache would not eliminate the need for per-method caching since the transformation would still need to run on every call.
Each method should cache its own processed results, following the existing getWatchHistory() pattern:
// Existing pattern in getWatchHistory()
const cacheKey = `${JELLYFIN_CACHE_KEYS.WATCH_HISTORY}:${itemId}`;
if (this.cache.data.has(cacheKey)) {
return this.cache.data.get<WatchRecord[]>(cacheKey) || [];
}
// ... compute ...
this.cache.data.set(cacheKey, records, JELLYFIN_CACHE_TTL.WATCH_HISTORY);
Summary
getWatchHistory()caches its processed results to avoid repeated per-user API calls across rule runs.getItemFavoritedBy()(#2393) andgetTotalPlayCount()use the same pattern — iterating all users viagetItemUserData()in batches — but neither caches their results.For a rule group scanning N items with M users, each uncached method adds N × M API calls per rule run.
Why per-method caching (not a shared
getItemUserDatacache)All three methods call
getItemUserData()internally, so caching at that level seems appealing. However, downstream consumers ofgetWatchHistory()depend on the processedWatchRecord[]format —Dateobjects parsed from ISO strings, filtering byPlayed: true, and defaults applied viaJellyfinMapper.toWatchRecord(). A rawgetItemUserData()cache would not eliminate the need for per-method caching since the transformation would still need to run on every call.Each method should cache its own processed results, following the existing
getWatchHistory()pattern: