@@ -26,17 +26,15 @@ import { Logger } from '@foxxmd/logging';
2626import { MemoryPositionalSource } from './MemoryPositionalSource.js' ;
2727import { FixedSizeList } from 'fixed-size-list' ;
2828import { SDKValidationError } from '@lukehagar/plexjs/sdk/models/errors/sdkvalidationerror.js' ;
29+ import { Keyv } from 'cacheable' ;
30+ import { initMemoryCache } from "../common/Cache.js" ;
2931
3032const shortDeviceId = truncateStringToLength ( 10 , '' ) ;
3133
3234export const LOCAL_USER = 'PLEX_LOCAL_USER' ;
3335
3436const THUMB_REGEX = new RegExp ( / \/ l i b r a r y \/ m e t a d a t a \/ (?< ratingkey > \d + ) \/ t h u m b \/ \d + / )
3537
36- type MbIdCacheEntry = { value : string | null , expiresAt : number } ;
37- const MBID_CACHE_TTL_MS = 10 * 60 * 1000 ;
38- const MBID_CACHE_SIZE = 1000 ;
39-
4038export default class PlexApiSource extends MemoryPositionalSource {
4139 users : string [ ] = [ ] ;
4240
@@ -63,7 +61,7 @@ export default class PlexApiSource extends MemoryPositionalSource {
6361
6462 libraries : { name : string , collectionType : string , uuid : string } [ ] = [ ] ;
6563
66- private mbIdCache = new Map < string , MbIdCacheEntry > ( ) ;
64+ private mbIdCache : Keyv < string > ;
6765
6866 declare config : PlexApiSourceConfig ;
6967
@@ -76,9 +74,11 @@ export default class PlexApiSource extends MemoryPositionalSource {
7674 this . deviceId = `${ name } -ms${ internal . version } -${ truncateStringToLength ( 10 , '' ) ( hashObject ( config ) ) } ` ;
7775 this . uniqueDropReasons = new FixedSizeList < string > ( 100 ) ;
7876 this . mediaIdsSeen = new FixedSizeList < string > ( 100 ) ;
77+ this . mbIdCache = initMemoryCache < string | null > ( { lruSize : 1000 , ttl : '1m' } ) as Keyv < string | null > ;
7978 }
8079
8180 protected async doBuildInitData ( ) : Promise < true | string | undefined > {
81+ this . regexCache
8282 const {
8383 data : {
8484 token,
@@ -418,14 +418,14 @@ export default class PlexApiSource extends MemoryPositionalSource {
418418 const prevBrainzMeta = sessionData [ 0 ] . play . data . meta . brainz ?? { } ;
419419 sessionData [ 0 ] . play . data . meta . brainz = {
420420 ...prevBrainzMeta ,
421- track : trackMbId ?? undefined ,
422- album : albumMbId ?? undefined ,
421+ track : trackMbId ,
422+ album : albumMbId ,
423423 // Plex doesn't track MBIDs for track artists, so we use the
424424 // album artist MBID instead.
425- artist : albumArtistMbId
425+ artist : albumArtistMbId !== undefined
426426 ? [ ...new Set ( [ ...( prevBrainzMeta . artist ?? [ ] ) , albumArtistMbId ] ) ]
427427 : prevBrainzMeta . artist ,
428- albumArtist : albumArtistMbId
428+ albumArtist : albumArtistMbId !== undefined
429429 ? [ ...new Set ( [ ...( prevBrainzMeta . albumArtist ?? [ ] ) , albumArtistMbId ] ) ]
430430 : prevBrainzMeta . albumArtist ,
431431 } ;
@@ -520,15 +520,18 @@ ${JSON.stringify(obj)}`);
520520
521521 getNewPlayer = ( logger : Logger , id : PlayPlatformId , opts : PlayerStateOptions ) => new PlexPlayerState ( logger , id , opts ) ;
522522
523- getMusicBrainzId = async ( ratingKey : string | undefined ) : Promise < string | null > => {
523+ getMusicBrainzId = async ( ratingKey : string | undefined ) : Promise < string | undefined > => {
524524 if ( ! ratingKey ) {
525525 return null ;
526526 }
527527
528- const cachedMbId = this . getCachedMbId ( ratingKey ) ;
529- if ( cachedMbId !== undefined ) {
528+ const cachedMbId = await this . mbIdCache . get ( ratingKey ) ;
529+ if ( cachedMbId !== undefined && cachedMbId !== null ) {
530530 return cachedMbId ;
531531 }
532+ if ( cachedMbId === null ) {
533+ return undefined ;
534+ }
532535
533536 try {
534537 // The current version of plexjs (0.39.0) does not return the GUID
@@ -555,55 +558,17 @@ ${JSON.stringify(obj)}`);
555558 if ( typeof guid . id === "string" && guid . id . startsWith ( "mbid://" ) ) {
556559 const mbid = guid . id . replace ( "mbid://" , "" ) ;
557560
558- this . setCachedMbId ( ratingKey , mbid ) ;
561+ await this . mbIdCache . set ( ratingKey , mbid ) ;
559562 return mbid ;
560563 }
561564 }
562565 }
563566 } catch ( e ) {
564- this . logger . warn ( `Failed to get MusicBrainz IDs from Plex for item ${ ratingKey } : ${ e } ` ) ;
565- }
566-
567- this . setCachedMbId ( ratingKey , null ) ;
568- return null ;
569- }
570-
571- getCachedMbId = ( ratingKey : string ) : string | null | undefined => {
572- const cachedMbId = this . mbIdCache . get ( ratingKey ) ;
573-
574- if ( ! cachedMbId ) {
575- return undefined ;
576- }
577-
578- if ( cachedMbId . expiresAt < Date . now ( ) ) {
579- this . mbIdCache . delete ( ratingKey ) ;
580- return undefined ;
567+ this . logger . warn ( new Error ( `Failed to get MusicBrainz IDs from Plex for item ${ ratingKey } ` , { cause : e } ) ) ;
581568 }
582569
583- return cachedMbId . value ;
584- }
585-
586- setCachedMbId = ( ratingKey : string , value : string | null ) => {
587- this . mbIdCache . set ( ratingKey , {
588- value,
589- expiresAt : Date . now ( ) + MBID_CACHE_TTL_MS ,
590- } ) ;
591-
592- // Clean up cache.
593- if ( this . mbIdCache . size > MBID_CACHE_SIZE ) {
594- const now = Date . now ( ) ;
595-
596- for ( const [ key , entry ] of this . mbIdCache ) {
597- if ( entry . expiresAt <= now ) {
598- this . mbIdCache . delete ( key ) ;
599- }
600- }
601-
602- while ( this . mbIdCache . size > MBID_CACHE_SIZE ) {
603- const oldestKey = this . mbIdCache . keys ( ) . next ( ) . value ;
604- this . mbIdCache . delete ( oldestKey ) ;
605- }
606- }
570+ this . mbIdCache . set ( ratingKey , null ) ;
571+ return undefined ;
607572 }
608573}
609574
0 commit comments