diff --git a/src/backend/common/infrastructure/config/common.ts b/src/backend/common/infrastructure/config/common.ts index 4cdb7f3f..e24407cc 100644 --- a/src/backend/common/infrastructure/config/common.ts +++ b/src/backend/common/infrastructure/config/common.ts @@ -48,5 +48,32 @@ export interface PollingOptions { * @examples [30] * */ maxInterval?: number + + /** + * Number of seconds after which A Player is considered Stale + * + * When Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale: + * + * * The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening) + * * If the player has an existing session w/ track then MS attempts to scrobble it + * + * This option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined. + */ + staleAfter?: number + + /** + * Number of seconds after which A Player is considered Orphaned + * + * When Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned: + * + * * The current Player session is ended and the Player is removed from MS + * * MS attempts to scrobble, if the Player has an existing session w/ track + * + * A Player should become Orphaned EQUAL TO OR AFTER it becomes Stale. + * + * * This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined. + * * If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`) + */ + orphanedAfter?: number } diff --git a/src/backend/sources/MemorySource.ts b/src/backend/sources/MemorySource.ts index e63985cc..0358a07b 100644 --- a/src/backend/sources/MemorySource.ts +++ b/src/backend/sources/MemorySource.ts @@ -141,7 +141,7 @@ export default class MemorySource extends AbstractSource { setNewPlayer = (idStr: string, logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions = {}) => { this.players.set(idStr, this.getNewPlayer(this.logger, id, { - ...createPlayerOptions(this.config.data as Partial), + ...createPlayerOptions(this.config.data as Partial, this.playerSourceOfTruth, this.logger), ...opts })); this.playerState.set(idStr, ''); diff --git a/src/backend/sources/PlayerState/AbstractPlayerState.ts b/src/backend/sources/PlayerState/AbstractPlayerState.ts index e3c13dfd..f3823148 100644 --- a/src/backend/sources/PlayerState/AbstractPlayerState.ts +++ b/src/backend/sources/PlayerState/AbstractPlayerState.ts @@ -30,22 +30,38 @@ export interface PlayerStateOptions extends PlayerStateIntervals { export const DefaultPlayerStateOptions: PlayerStateOptions = {}; -export const createPlayerOptions = (pollingOpts?: Partial, sot: SOURCE_SOT_TYPES = SOURCE_SOT.PLAYER): PlayerStateOptions => { +export const createPlayerOptions = (pollingOpts?: Partial, sot: SOURCE_SOT_TYPES = SOURCE_SOT.PLAYER, logger?: Logger): PlayerStateOptions => { const { interval = 30, maxInterval = 60, + staleAfter, + orphanedAfter } = pollingOpts || {}; - if(sot === SOURCE_SOT.PLAYER) { - return { - staleInterval: interval * 3, - orphanedInterval: interval * 5 - } - } + + let sa = staleAfter, + oa = orphanedAfter; + // if this player is not the source of truth we don't care about waiting around to see if the state comes back // in fact, we probably want to get rid of it as fast as possible since its superficial and more of an ephemeral "Now Playing" status than something we are actually tracking + const staleAfterDefault = sot === SOURCE_SOT.PLAYER ? interval * 3 : interval; + const orphanedAfterDefault = sot === SOURCE_SOT.PLAYER ? interval * 5 : maxInterval; + + if(sa === undefined) { + sa = staleAfterDefault; + } + if(oa === undefined) { + oa = orphanedAfterDefault; + } + if(oa < sa) { + oa = sa; + if(logger !== undefined) { + logger.warn(`'orhanedAfter' (${oa}s) was less than 'staleAfter' (${sa}s) which is not allowed! 'orhanedAfter' has been set to equal 'staleAfter'`); + } + } + return { - staleInterval: interval, - orphanedInterval: maxInterval + staleInterval: sa, + orphanedInterval: oa } }