Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/682 slow loading of queue #684

Merged
merged 2 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading