start the download before fetching its artwork

- The artwork step no longer holds up the media: the song goes to the platform
  first and the art is fetched afterwards, in the same foreground window. A
  stalled artwork server can no longer delay a download, and a process death
  during the fetch can no longer lose the download entirely.
- Resuming a queued download after a restart fetches its artwork now too; only a
  fresh download did before.
- The artwork budget is a minute rather than ten seconds, which costs nothing but
  a live coroutine now that nothing waits on it for the media.
- OkHttpArtworkFetcher derives a client with a per-call timeout. A blocking
  OkHttp call is not interrupted by a coroutine timeout, so without it the outer
  budget bounded our wait but not the socket.
This commit is contained in:
austinried
2026-10-04 00:30:01 +00:00
parent 11cc5e9ab8
commit 6942798bf2
3 changed files with 89 additions and 27 deletions
@@ -46,10 +46,12 @@ class DownloadRepositoryTest {
private lateinit var dir: File
private val messages = CopyOnWriteArrayList<String>()
private val requestedArt = CopyOnWriteArrayList<String>()
private val artFetchedAfterTheEngineRequest = CopyOnWriteArrayList<Boolean>()
private var failArtworkFetch = false
private val fetcher =
ArtworkFetcher { url ->
requestedArt += url
artFetchedAfterTheEngineRequest += engine.requests.isNotEmpty()
if (failArtworkFetch) throw IOException("boom")
byteArrayOf(1, 2, 3)
}
@@ -312,6 +314,29 @@ class DownloadRepositoryTest {
}
}
@Test
fun theDownloadStartsBeforeItsArtworkIsFetched() =
runTest {
seedLibrary()
runBlocking { repository.download(1, "s1") }
assertTrue(artFetchedAfterTheEngineRequest.isNotEmpty())
assertTrue(artFetchedAfterTheEngineRequest.all { it })
}
@Test
fun resumingAQueuedDownloadAlsoStoresItsArtwork() =
runTest {
seedLibrary()
db.downloadDao().upsert(SongDownload(1, "s1", DownloadStatus.Queued, engineId = 7))
runBlocking { repository.reconcile() }
assertEquals(1, engine.requests.size)
assertNotNull(artwork.uri(1, coverArtKey(1, ALBUM_ART, false)))
}
@Test
fun aSongWithoutArtworkStillDownloads() =
runTest {