From ab8d08cc9b08c4b1a94564b6784cd9974b8fae73 Mon Sep 17 00:00:00 2001 From: amendelsohn Date: Wed, 7 Dec 2022 17:41:49 -0500 Subject: [PATCH] queue optimizations; batch action for tracks --- .../offline-download-queue.ts | 29 ++++++++++++++----- .../offline-downloader/offline-downloader.ts | 8 +++++ .../src/store/offline-downloads/slice.ts | 9 ++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/mobile/src/services/offline-downloader/offline-download-queue.ts b/packages/mobile/src/services/offline-downloader/offline-download-queue.ts index 717b9a0914..dc01684abb 100644 --- a/packages/mobile/src/services/offline-downloader/offline-download-queue.ts +++ b/packages/mobile/src/services/offline-downloader/offline-download-queue.ts @@ -1,7 +1,10 @@ import queue, { Worker } from 'react-native-job-queue' import { store } from 'app/store' -import { errorDownload, startDownload } from 'app/store/offline-downloads/slice' +import { + batchStartDownload, + errorDownload +} from 'app/store/offline-downloads/slice' import { downloadTrack } from './offline-downloader' @@ -16,8 +19,6 @@ export const enqueueTrackDownload = async ( trackId: number, collection: string ) => { - store.dispatch(startDownload(trackId.toString())) - queue.addJob( TRACK_DOWNLOAD_WORKER, { trackId, collection }, @@ -41,23 +42,35 @@ export const startDownloadWorker = async () => { if (worker) queue.removeWorker(TRACK_DOWNLOAD_WORKER, true) queue.addWorker( new Worker(TRACK_DOWNLOAD_WORKER, downloadTrack, { - onFailure: ({ payload }) => - store.dispatch(errorDownload(payload.trackId.toString())), + onFailure: ({ payload }) => { + store.dispatch(errorDownload(payload.trackId.toString())) + }, concurrency: 10 }) ) + + // Sync leftover jobs from last session to redux state const jobs = await queue.getJobs() + const trackIdsInQueue: string[] = [] jobs .filter((job) => job.workerName === TRACK_DOWNLOAD_WORKER) - .forEach(({ payload }) => { + .forEach((job) => { try { + const { payload, failed } = job const parsedPayload: TrackDownloadWorkerPayload = JSON.parse(payload) const trackId = parsedPayload.trackId - store.dispatch(startDownload(trackId.toString())) + if (failed) { + store.dispatch(errorDownload(trackId.toString())) + queue.removeJob(job) + } else { + trackIdsInQueue.push(parsedPayload.trackId.toString()) + } } catch (e) { console.warn(e) } }) - setTimeout(queue.start, 1000) + store.dispatch(batchStartDownload(trackIdsInQueue)) + + queue.start() } diff --git a/packages/mobile/src/services/offline-downloader/offline-downloader.ts b/packages/mobile/src/services/offline-downloader/offline-downloader.ts index a447885f5f..989d9d8eb1 100644 --- a/packages/mobile/src/services/offline-downloader/offline-downloader.ts +++ b/packages/mobile/src/services/offline-downloader/offline-downloader.ts @@ -13,6 +13,7 @@ import RNFS, { exists } from 'react-native-fs' import { store } from 'app/store' import { addCollection, + batchStartDownload, startDownload, completeDownload, errorDownload, @@ -46,6 +47,7 @@ export const downloadCollection = async ( ) => { store.dispatch(addCollection(collection)) persistCollectionDownloadStatus(collection, true) + store.dispatch(batchStartDownload(trackIds.map(toString))) trackIds.forEach((trackId) => enqueueTrackDownload(trackId, collection)) } @@ -100,6 +102,12 @@ export const downloadTrack = async ({ if (!track) { throw failJob(`track to download not found on discovery - ${trackIdStr}`) } + if ( + track?.is_delete || + (track?.is_unlisted && currentUserId !== track.user.user_id) + ) { + throw failJob(`track to download is not available - ${trackIdStr}`) + } track = (await populateCoverArtSizes(track)) ?? track diff --git a/packages/mobile/src/store/offline-downloads/slice.ts b/packages/mobile/src/store/offline-downloads/slice.ts index 2befb51052..d768021fb2 100644 --- a/packages/mobile/src/store/offline-downloads/slice.ts +++ b/packages/mobile/src/store/offline-downloads/slice.ts @@ -35,6 +35,14 @@ const slice = createSlice({ startDownload: (state, { payload: trackId }: PayloadAction) => { state.downloadStatus[trackId] = OfflineTrackDownloadStatus.LOADING }, + batchStartDownload: ( + state, + { payload: trackIds }: PayloadAction + ) => { + trackIds.forEach((trackId) => { + state.downloadStatus[trackId] = OfflineTrackDownloadStatus.LOADING + }) + }, completeDownload: (state, { payload: trackId }: PayloadAction) => { state.downloadStatus[trackId] = OfflineTrackDownloadStatus.SUCCESS }, @@ -77,6 +85,7 @@ const slice = createSlice({ export const { startDownload, + batchStartDownload, completeDownload, errorDownload, removeDownload,