diff --git a/src/backend/sources/JellyfinApiSource.ts b/src/backend/sources/JellyfinApiSource.ts index c60dde83..7c50486b 100644 --- a/src/backend/sources/JellyfinApiSource.ts +++ b/src/backend/sources/JellyfinApiSource.ts @@ -53,6 +53,7 @@ import { JellyApiSourceConfig } from "../common/infrastructure/config/source/jel import { combinePartsToString, genGroupIdStr, getPlatformIdFromData, joinedUrl, parseBool, } from "../utils.js"; import { parseArrayFromMaybeString } from "../utils/StringUtils.js"; import { MemoryPositionalSource } from "./MemoryPositionalSource.js"; +import { FixedSizeList } from "fixed-size-list"; const shortDeviceId = truncateStringToLength(10, ''); @@ -78,7 +79,8 @@ export default class JellyfinApiSource extends MemoryPositionalSource { logFilterFailure: false | 'debug' | 'warn'; - mediaIdsSeen: string[] = []; + mediaIdsSeen: FixedSizeList; + uniqueDropReasons: FixedSizeList; libraries: {name: string, paths: string[], collectionType: CollectionType}[] = []; @@ -101,6 +103,9 @@ export default class JellyfinApiSource extends MemoryPositionalSource { id: this.deviceId } }); + + this.uniqueDropReasons = new FixedSizeList(100); + this.mediaIdsSeen = new FixedSizeList(100); } protected async doBuildInitData(): Promise { @@ -413,8 +418,13 @@ export default class JellyfinApiSource extends MemoryPositionalSource { let stateIdentifyingInfo: string = genGroupIdStr(getPlatformIdFromData(sessionData[0])); if(sessionData[0].play !== undefined) { stateIdentifyingInfo = buildTrackString(sessionData[0].play, {include: ['artist', 'track', 'platform']}); - } - this.logger[this.logFilterFailure](`Player State for -> ${stateIdentifyingInfo} <-- is being dropped because ${validPlay}`); + } + const dropReason = `Player State for -> ${stateIdentifyingInfo} <-- is being dropped because ${validPlay}`; + if(!this.uniqueDropReasons.data.some(x => x === dropReason)) { + this.logger[this.logFilterFailure](dropReason); + this.uniqueDropReasons.add(dropReason); + } + this.logger[this.logFilterFailure](dropReason); } } return this.processRecentPlays(validSessions); @@ -454,9 +464,9 @@ export default class JellyfinApiSource extends MemoryPositionalSource { } } - if(this.config.options.logPayload && !this.mediaIdsSeen.includes(NowPlayingItem.Id)) { + if(this.config.options.logPayload && !this.mediaIdsSeen.data.includes(NowPlayingItem.Id)) { this.logger.debug(`First time seeing media ${NowPlayingItem.Id} on ${msDeviceId} (play position ${playerPosition}) => ${JSON.stringify(NowPlayingItem)}`); - this.mediaIdsSeen.push(NowPlayingItem.Id); + this.mediaIdsSeen.add(NowPlayingItem.Id); } } diff --git a/src/backend/sources/PlexApiSource.ts b/src/backend/sources/PlexApiSource.ts index 5774605c..6248328e 100644 --- a/src/backend/sources/PlexApiSource.ts +++ b/src/backend/sources/PlexApiSource.ts @@ -26,6 +26,7 @@ import { PlexPlayerState } from './PlayerState/PlexPlayerState.js'; import { PlayerStateOptions } from './PlayerState/AbstractPlayerState.js'; import { Logger } from '@foxxmd/logging'; import { MemoryPositionalSource } from './MemoryPositionalSource.js'; +import { FixedSizeList } from 'fixed-size-list'; const shortDeviceId = truncateStringToLength(10, ''); @@ -50,7 +51,8 @@ export default class PlexApiSource extends MemoryPositionalSource { logFilterFailure: false | 'debug' | 'warn'; - mediaIdsSeen: string[] = []; + mediaIdsSeen: FixedSizeList; + uniqueDropReasons: FixedSizeList; libraries: {name: string, collectionType: string, uuid: string}[] = []; @@ -63,6 +65,8 @@ export default class PlexApiSource extends MemoryPositionalSource { this.requiresAuth = true; this.requiresAuthInteraction = false; this.deviceId = `${name}-ms${internal.version}-${truncateStringToLength(10, '')(objectHash.sha1(config))}`; + this.uniqueDropReasons = new FixedSizeList(100); + this.mediaIdsSeen = new FixedSizeList(100); } protected async doBuildInitData(): Promise { @@ -337,8 +341,12 @@ export default class PlexApiSource extends MemoryPositionalSource { let stateIdentifyingInfo: string = genGroupIdStr(getPlatformIdFromData(sessionData[0])); if(sessionData[0].play !== undefined) { stateIdentifyingInfo = buildTrackString(sessionData[0].play, {include: ['artist', 'track', 'platform']}); - } - this.logger[this.logFilterFailure](`Player State for -> ${stateIdentifyingInfo} <-- is being dropped because ${validPlay}`); + } + const dropReason = `Player State for -> ${stateIdentifyingInfo} <-- is being dropped because ${validPlay}`; + if(!this.uniqueDropReasons.data.some(x => x === dropReason)) { + this.logger[this.logFilterFailure](dropReason); + this.uniqueDropReasons.add(dropReason); + } } } return this.processRecentPlays(validSessions); @@ -378,9 +386,9 @@ export default class PlexApiSource extends MemoryPositionalSource { const play: PlayObject = this.formatPlayObjAware(obj); - if(this.config.options.logPayload && !this.mediaIdsSeen.includes(play.meta.trackId)) { + if(this.config.options.logPayload && !this.mediaIdsSeen.data.includes(play.meta.trackId)) { this.logger.debug(`First time seeing media ${play.meta.trackId} on ${msDeviceId} => ${JSON.stringify(play)}`); - this.mediaIdsSeen.push(play.meta.trackId); + this.mediaIdsSeen.add(play.meta.trackId); } const reportedStatus = state !== 'playing' ? REPORTED_PLAYER_STATUSES.paused : REPORTED_PLAYER_STATUSES.playing;