music: cleanup old cover revisions

This commit is contained in:
Alexander Capehart 2024-12-24 09:45:26 -05:00
parent 8409a93c4e
commit 0cfd6ddb67
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 26 additions and 23 deletions

View file

@ -25,6 +25,7 @@ import javax.inject.Inject
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
@ -361,25 +362,18 @@ constructor(
}
val locations = musicSettings.musicLocations
val revision: UUID
val storage: Storage
if (withCache) {
revision = musicSettings.revision
storage =
Storage(cache, MutableRevisionedStoredCovers(context, revision), storedPlaylists)
} else {
revision = UUID.randomUUID()
storage =
Storage(
WriteOnlyCache(cache),
MutableRevisionedStoredCovers(context, revision),
storedPlaylists)
}
val currentRevision = musicSettings.revision
val newRevision = currentRevision?.takeIf { withCache } ?: UUID.randomUUID()
val cache = if (withCache) cache else WriteOnlyCache(cache)
val covers = MutableRevisionedStoredCovers(context, newRevision)
val storage = Storage(cache, covers, storedPlaylists)
val interpretation = Interpretation(nameFactory, separators)
val newLibrary =
Musikr.new(context, storage, interpretation).run(locations, ::emitIndexingProgress)
// Music loading completed, update the revision right now so we re-use this work
// later.
musicSettings.revision = newRevision
emitIndexingCompletion(null)
@ -415,8 +409,9 @@ constructor(
dispatchLibraryChange(deviceLibraryChanged, userLibraryChanged)
}
// Quietly update the revision if needed (this way we don't disrupt any new loads)
musicSettings.revision = revision
// Old cover revisions may be lying around, even during a normal refresh due
// to realyl lucky cancellations. Clean those up.
RevisionedStoredCovers.cleanup(context, newRevision)
}
private suspend fun emitIndexingProgress(progress: IndexingProgress) {

View file

@ -35,7 +35,7 @@ import timber.log.Timber as L
*/
interface MusicSettings : Settings<MusicSettings.Listener> {
/** The current library revision. */
var revision: UUID
var revision: UUID?
/** The locations of music to load. */
var musicLocations: List<MusicLocation>
/** Whether to exclude non-music audio files from the music library. */
@ -58,11 +58,9 @@ interface MusicSettings : Settings<MusicSettings.Listener> {
class MusicSettingsImpl @Inject constructor(@ApplicationContext private val context: Context) :
Settings.Impl<MusicSettings.Listener>(context), MusicSettings {
override var revision: UUID
override var revision: UUID?
get() =
UUID.fromString(
sharedPreferences.getString(getString(R.string.set_key_library_revision), null)
?: UUID.randomUUID().toString())
sharedPreferences.getString(getString(R.string.set_key_library_revision), null)?.let(UUID::fromString)
set(value) {
sharedPreferences.edit {
putString(getString(R.string.set_key_library_revision), value.toString())

View file

@ -19,12 +19,15 @@
package org.oxycblt.auxio.music
import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.UUID
import org.oxycblt.auxio.util.unlikelyToBeNull
import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.CoverFormat
import org.oxycblt.musikr.cover.MutableStoredCovers
import org.oxycblt.musikr.cover.StoredCovers
import java.io.File
open class RevisionedStoredCovers(private val context: Context, private val revision: UUID?) :
StoredCovers {
@ -48,6 +51,13 @@ open class RevisionedStoredCovers(private val context: Context, private val revi
return storedCovers.obtain(coverId)?.let { RevisionedCover(coverRevision, it) }
}
}
companion object {
suspend fun cleanup(context: Context, exclude: UUID) = withContext(Dispatchers.IO) {
context.filesDir.listFiles { file -> file.name.startsWith("covers_") && file.name != "covers_$exclude" }
?.forEach { it.deleteRecursively() }
}
}
}
class MutableRevisionedStoredCovers(context: Context, private val revision: UUID) :