[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: Improve cache stats

* Remove vsize since its very inaccurate
* Use memory store `size` for count, if present

FoxxMD (Mar 27, 2026, 8:30 PM UTC) 06945fda 306c4c85

+19 -14
+19 -14
src/backend/common/Cache.ts
··· 1 - import { Cacheable, createKeyv, Keyv, KeyvStoreAdapter, KeyvOptions, CacheableOptions } from 'cacheable'; 1 + import { Cacheable, createKeyv, Keyv, KeyvStoreAdapter, KeyvOptions, CacheableOptions, KeyvCacheableMemory } from 'cacheable'; 2 2 import { FlatCache, FlatCacheOptions } from 'flat-cache'; 3 3 import KeyvValkey from '@keyv/valkey'; 4 4 import dayjs, { Dayjs } from 'dayjs'; ··· 59 59 cacheMisses: Gauge; 60 60 cacheSets: Gauge; 61 61 cacheCount: Gauge; 62 - cacheVSize: Gauge; 62 + //cacheVSize: Gauge; 63 63 64 64 constructor(logger: Logger, config: CacheConfigOptions = {}) { 65 65 this.logger = childLogger(logger, 'Cache'); ··· 186 186 } 187 187 }); 188 188 189 - this.cacheVSize = new prom.Gauge({ 190 - name: 'multiscrobbler_cache_vsize', 191 - help: 'estimated byte size of values in cache', 192 - labelNames: ['cacheType', 'tier'], 193 - collect() { 194 - for(const set of collectors) { 195 - const [primary] = getStat(set.cache, 'vsize', false); 196 - this.labels({cacheType: set.name, tier: 'primary'}).set(primary); 197 - } 198 - } 199 - }); 189 + // this.cacheVSize = new prom.Gauge({ 190 + // name: 'multiscrobbler_cache_vsize', 191 + // help: 'estimated byte size of values in cache', 192 + // labelNames: ['cacheType', 'tier'], 193 + // collect() { 194 + // for(const set of collectors) { 195 + // const [primary] = getStat(set.cache, 'vsize', false); 196 + // this.labels({cacheType: set.name, tier: 'primary'}).set(primary); 197 + // } 198 + // } 199 + // }); 200 200 } 201 201 202 202 protected initCacheable = async (config: CacheConfig, cacheFor: string) => { ··· 286 286 const memory = createKeyv({ 287 287 ttl, 288 288 lruSize, 289 + // millisecond interval before checking for expired keys and deleting 290 + checkInterval: 10000, 289 291 ...restOpts, 290 292 useClone: false, 291 293 }); ··· 415 417 } 416 418 417 419 const getStat = (cache: Cacheable, statName: string, getSecondary: boolean = true): [number, number?] => { 418 - const primary = cache.stats[statName]; 420 + let primary = cache.stats[statName]; 421 + if(statName === 'count' && cache.primary.store instanceof KeyvCacheableMemory) { 422 + primary = cache.primary.store.store.size; 423 + } 419 424 let secondary: number; 420 425 if(getSecondary && cache.secondary !== undefined) { 421 426 secondary = cache.secondary.stats[statName];