diff --git a/src/backend/scrobblers/AbstractHistoricalScrobbleClient.ts b/src/backend/scrobblers/AbstractHistoricalScrobbleClient.ts index 11d10a26..7b215e2f 100644 --- a/src/backend/scrobblers/AbstractHistoricalScrobbleClient.ts +++ b/src/backend/scrobblers/AbstractHistoricalScrobbleClient.ts @@ -123,7 +123,7 @@ export default abstract class AbstractHistoricalScrobbleClient extends AbstractS return closeTemporalPlays.map(x => x.play); } - protected abstract syncRecentHistoricalScrobbles(): Promise; + protected abstract syncRecentHistoricalScrobbles(): Promise<[PlayObject[], boolean]>; protected async postInitialize(): Promise { await super.postInitialize(); @@ -148,13 +148,21 @@ export default abstract class AbstractHistoricalScrobbleClient extends AbstractS if(shouldSync){ // pull latest plays into database this.logger.info('Pulling latest scrobbles into historical database...'); - const recent = await this.syncRecentHistoricalScrobbles(); + const [recent, gapSynced] = await this.syncRecentHistoricalScrobbles(); if(recent.length > 0) { await this.createHistoricalPlays(recent.map((x) => playToRepositoryCreatePlayHistoricalOpts({play: x}))); this.logger.verbose(`Added ${recent.length} upstream plays to historical plays`); } else { this.logger.verbose('Most recent plays are already in historical database!'); } + if(this.syncedReason.includes('component was inactive')) { + if(gapSynced) { + this.syncedReason = undefined; + this.logger.verbose('Sync gap was verified filled by pulling latest scrobbles!'); + } else { + this.logger.verbose('Pulling latest scrobbles did not fill inactivity period. You may want to run historical hydration again.'); + } + } } }).catch((e) => this.logger.warn(new Error('Failed to complete post-init historical database sync but continuing anyway', {cause: e}))); @@ -167,6 +175,9 @@ export default abstract class AbstractHistoricalScrobbleClient extends AbstractS const [synced, reason] = await this.getHistoricalScrobblesAreSynced(); this.synced = synced; this.syncedReason = reason; + if(this.syncedReason !== undefined) { + this.logger.info(`Sync status is abnormal: ${this.syncedReason}`); + } if(imports.length > 0) { imports.sort((a, b) => sortByNewestDate(a.attemptedAt, b.attemptedAt)); this.lastImport = imports[0].attemptedAt; diff --git a/src/backend/scrobblers/RockskyScrobbler.ts b/src/backend/scrobblers/RockskyScrobbler.ts index 6df46984..a7423ca9 100644 --- a/src/backend/scrobblers/RockskyScrobbler.ts +++ b/src/backend/scrobblers/RockskyScrobbler.ts @@ -242,14 +242,17 @@ export default class RockskyScrobbler extends AbstractHistoricalScrobbleClient { logger.info(`Completed CAR conversion: Result ${allGood ? 'OK' : 'Some Errors'} in ${durationToHuman(dayjs.duration(dayjs().diff(start)))} | Records ${count} | Persisted ${persisted}`) } - protected async syncRecentHistoricalScrobbles(): Promise { + protected async syncRecentHistoricalScrobbles(): Promise<[PlayObject[], boolean]> { const recentPlays = await this.getScrobblesForTimeRange(undefined); const unseenPlays: PlayObject[] = []; + let syncGapFilled = false; for (const p of recentPlays) { if(!(await this.playsHistoricalRepo.hasByUid(p.meta.playId))) { unseenPlays.push(p); + } else { + syncGapFilled = true; } } - return unseenPlays; + return [unseenPlays, syncGapFilled]; } } diff --git a/src/backend/scrobblers/TealfmScrobbler.ts b/src/backend/scrobblers/TealfmScrobbler.ts index bca55cac..d4aa55b1 100644 --- a/src/backend/scrobblers/TealfmScrobbler.ts +++ b/src/backend/scrobblers/TealfmScrobbler.ts @@ -291,15 +291,18 @@ export default class TealScrobbler extends AbstractHistoricalScrobbleClient { logger.info(`Completed CAR conversion: Result ${allGood ? 'OK' : 'Some Errors'} in ${durationToHuman(dayjs.duration(dayjs().diff(start)))} | Records ${count} | Persisted ${persisted}`) } - protected async syncRecentHistoricalScrobbles(): Promise { + protected async syncRecentHistoricalScrobbles(): Promise<[PlayObject[], boolean]> { const recentPlays = await this.getScrobblesForTimeRange(undefined); const unseenPlays: PlayObject[] = []; + let syncGapFilled = false; for(const p of recentPlays) { if(!(await this.playsHistoricalRepo.hasByUid(p.meta.playId))) { unseenPlays.push(p); + } else { + syncGapFilled = true; } } - return unseenPlays; + return [unseenPlays, syncGapFilled]; } }