From 0cfd6ddb67dca3da1804d86f6039e39f0a538b8f Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Tue, 24 Dec 2024 09:45:26 -0500 Subject: [PATCH] music: cleanup old cover revisions --- .../oxycblt/auxio/music/MusicRepository.kt | 29 ++++++++----------- .../org/oxycblt/auxio/music/MusicSettings.kt | 8 ++--- .../oxycblt/auxio/music/RevisionedLibrary.kt | 12 +++++++- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt index 8d76fac26..7509049f1 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt @@ -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) { diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt index a7a55ec8d..d4ceb6131 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt @@ -35,7 +35,7 @@ import timber.log.Timber as L */ interface MusicSettings : Settings { /** The current library revision. */ - var revision: UUID + var revision: UUID? /** The locations of music to load. */ var musicLocations: List /** Whether to exclude non-music audio files from the music library. */ @@ -58,11 +58,9 @@ interface MusicSettings : Settings { class MusicSettingsImpl @Inject constructor(@ApplicationContext private val context: Context) : Settings.Impl(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()) diff --git a/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt b/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt index 945092a7a..6ad9d5572 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt @@ -15,16 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + 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) :