[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.

fix(scrobbler): Fix try-catch block so queued scrobble is always added, even if existing queued check fails

FoxxMD (May 27, 2026, 7:24 PM UTC) 405ee4f6 34e0eaef

+18 -21
+18 -21
src/backend/scrobblers/AbstractScrobbleClient.ts
··· 1404 1404 for await(const play of pMapIterable(playDatas, this.staggerMappers.preCompare(async x => transformFunc !== undefined ? await transformFunc(x) : await this.transformPlay(x, TRANSFORM_HOOK.preCompare)), {concurrency: 3})) { 1405 1405 try { 1406 1406 // cheap check, looks for play data (non-meta) hash, playdate, and optionally mbid recording 1407 - const cheapExisting = await this.playRepo.checkExisting(play, {queueName: CLIENT_INGRESS_QUEUE}); 1408 - if(cheapExisting !== undefined) { 1407 + const cheapExisting = await this.playRepo.checkExisting(play, { queueName: CLIENT_INGRESS_QUEUE }); 1408 + if (cheapExisting !== undefined) { 1409 1409 const qs = cheapExisting.queueStates.find(x => x.queueName === CLIENT_INGRESS_QUEUE); 1410 1410 this.logger.trace(`Not adding to queue because it is already in the queue, discovered via hash/mbid, last queued at ${todayAwareFormat(qs.createdAt)}`); 1411 1411 continue; ··· 1413 1413 // then chunked queued plays 1414 1414 let offset = 0; 1415 1415 let inQueue = false; 1416 - while(true) { 1417 - const {data, meta} = await this.playRepo.getQueued(CLIENT_INGRESS_QUEUE, {offset}); 1416 + while (true) { 1417 + const { data, meta } = await this.playRepo.getQueued(CLIENT_INGRESS_QUEUE, { offset }); 1418 1418 const existingQueued = await this.existingScrobble(play, data.map(x => asPlay(x.play)), false); 1419 - // want to be very confident of this 1420 - if(existingQueued.match && existingQueued.score > 0.99) { 1419 + // want to be very confident of this 1420 + if (existingQueued.match && existingQueued.score > 0.99) { 1421 1421 this.logger.trace(`Not adding to queue because it is already in the queue\n${existingQueued.summary}`); 1422 1422 inQueue = true; 1423 1423 break; 1424 1424 } 1425 - if(data.length < meta.limit) { 1425 + if (data.length < meta.limit) { 1426 1426 break; 1427 1427 } 1428 1428 offset += meta.limit; 1429 1429 } 1430 1430 1431 - if(inQueue) { 1431 + if (inQueue) { 1432 1432 continue; 1433 1433 } 1434 - 1435 - // not in queue! 1436 - const { 1437 - meta: { 1438 - // dbId, 1439 - // dbUid, 1440 - lifecycle, 1441 - ...metaRest 1442 - }, 1443 - } = play 1434 + } catch (e) { 1435 + this.logger.warn(new SimpleError('Failed to check queued scrobble for existing before adding, will continue with adding anyway', { cause: e })); 1436 + } 1437 + // not in queue or existing queued check failed for some reason and we don't want to lose scrobble 1438 + const { 1439 + meta: { 1440 + lifecycle, 1441 + ...metaRest 1442 + }, 1443 + } = play 1444 1444 const createPlayData = playToRepositoryCreatePlayOpts({ 1445 1445 play: { 1446 1446 ...play, ··· 1461 1461 createdQueuedPlays.push(playRow[0]); 1462 1462 this.logger.debug(`Added ${buildTrackString(play)} to the queue`); 1463 1463 1464 - } catch (e) { 1465 - this.logger.warn(new SimpleError('Failed to check queued scrobble for existing before adding', {cause: e})); 1466 - } 1467 1464 const queuedPlay = {id: nanoid(), source, play: play} 1468 1465 //await this.playRepo.updateById(play.meta.dbId, {play}); 1469 1466 this.emitEvent('scrobbleQueued', {queuedPlay: queuedPlay});