Skip to content

Commit

Permalink
Bugfix/682 slow loading of queue (#684)
Browse files Browse the repository at this point in the history
* Already much faster

* Now we're blazing fast!
  • Loading branch information
digimezzo authored Sep 15, 2024
1 parent 2b87874 commit e15cdb5
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/app/data/repositories/track-repository.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export abstract class TrackRepositoryBase {
public abstract getTracksForTrackArtists(trackArtists: string[]): Track[] | undefined;
public abstract getTracksForAlbumArtists(albumArtists: string[]): Track[] | undefined;
public abstract getTracksForGenres(genres: string[]): Track[] | undefined;
public abstract getTracksForPaths(paths: string[]): Track[] | undefined;
public abstract getAlbumDataForAlbumKey(albumKeyIndex: string, albumKey: string): AlbumData[] | undefined;
public abstract getAllAlbumData(albumKeyIndex: string): AlbumData[] | undefined;
public abstract getAlbumDataForTrackArtists(albumKeyIndex: string, trackArtists: string[]): AlbumData[] | undefined;
Expand Down
16 changes: 16 additions & 0 deletions src/app/data/repositories/track-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ export class TrackRepository implements TrackRepositoryBase {
return tracks;
}

public getTracksForPaths(paths: string[]): Track[] | undefined {
const database: any = this.databaseFactory.create();

let filterQuery: string = '';

if (paths != undefined && paths.length > 0) {
filterQuery = ` AND ${ClauseCreator.createTextInClause('t.Path', paths)}`;
}

const statement = database.prepare(`${QueryParts.selectTracksQueryPart(true)} ${filterQuery};`);

const tracks: Track[] | undefined = statement.all();

return tracks;
}

public getAlbumDataThatNeedsIndexing(albumKeyIndex: string): AlbumData[] | undefined {
const database = this.databaseFactory.create();

Expand Down
61 changes: 49 additions & 12 deletions src/app/services/playback/queue-persister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ import { QueuedTrack } from '../../data/entities/queued-track';
import { TrackModel } from '../track/track-model';
import { QueueRestoreInfo } from './queue-restore-info';
import { TrackModelFactory } from '../track/track-model-factory';
import {SettingsBase} from "../../common/settings/settings.base";
import { SettingsBase } from '../../common/settings/settings.base';
import { Track } from '../../data/entities/track';
import { TrackRepositoryBase } from '../../data/repositories/track-repository.base';
import { Timer } from '../../common/scheduling/timer';

@Injectable({ providedIn: 'root' })
export class QueuePersister {
public constructor(
private queuedTrackRepository: QueuedTrackRepositoryBase,
private trackRepository: TrackRepositoryBase,
private trackModelFactory: TrackModelFactory,
private settings: SettingsBase,
private logger: Logger,
Expand Down Expand Up @@ -60,28 +64,61 @@ export class QueuePersister {
return new QueueRestoreInfo([], [], undefined, 0);
}

const tracks: TrackModel[] = [];
const tracksModels: TrackModel[] = [];
const playbackOrder: number[] = new Array<number>(savedQueuedTracks.length).fill(0);
let playingTrack: TrackModel | undefined = undefined;
let progressSeconds: number = 0;

const albumKeyIndex = this.settings.albumKeyIndex;
const tracks: Track[] | undefined = this.trackRepository.getTracksForPaths(savedQueuedTracks.map((x) => x.path));

if (!tracks || tracks.length === 0) {
this.logger.info(`No tracks found for saved queued tracks.`, 'QueuePersister', 'restore');
return new QueueRestoreInfo([], [], undefined, 0);
}

for (const savedQueuedTrack of savedQueuedTracks) {
const track: TrackModel = await this.trackModelFactory.createFromFileAsync(savedQueuedTrack.path, albumKeyIndex);
const timer = new Timer();
timer.start();

tracks.push(track);
playbackOrder[savedQueuedTrack.orderId] = tracks.length - 1;
const albumKeyIndex = this.settings.albumKeyIndex;

if (savedQueuedTrack.isPlaying) {
playingTrack = track;
progressSeconds = savedQueuedTrack.progressSeconds;
const trackMap = new Map(savedQueuedTracks.map((track) => [track.path, track]));
const orderedTracks = tracks
.sort((a, b) => {
const orderA = trackMap.get(a.path)?.orderId ?? 0;
const orderB = trackMap.get(b.path)?.orderId ?? 0;
return orderA - orderB;
})
.map((track) => {
const savedTrack = trackMap.get(track.path);
return {
...track,
isPlaying: savedTrack?.isPlaying ?? 0,
orderId: savedTrack?.orderId ?? 0,
progressSeconds: savedTrack?.progressSeconds ?? 0,
};
});

for (const orderedTrack of orderedTracks) {
const trackModel: TrackModel = this.trackModelFactory.createFromTrack(orderedTrack, albumKeyIndex);

tracksModels.push(trackModel);
playbackOrder[orderedTrack.orderId] = tracksModels.length - 1;

if (orderedTrack.isPlaying) {
playingTrack = trackModel;
progressSeconds = orderedTrack.progressSeconds;
}
}

this.logger.info(`Restored queue of ${savedQueuedTracks.length} tracks`, 'QueuePersister', 'restore');
timer.stop();

this.logger.info(
`Restored queue of ${savedQueuedTracks.length} tracks. Time required: ${timer.elapsedMilliseconds} ms`,
'QueuePersister',
'restore',
);

return new QueueRestoreInfo(tracks, playbackOrder, playingTrack, progressSeconds);
return new QueueRestoreInfo(tracksModels, playbackOrder, playingTrack, progressSeconds);
} catch (e: unknown) {
if (e instanceof Error) {
this.logger.error(e, 'Failed to restore queue', 'QueuePersister', 'restore');
Expand Down

0 comments on commit e15cdb5

Please sign in to comment.