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

View file

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

View file

@ -15,16 +15,19 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.content.Context import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.UUID import java.util.UUID
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.CoverFormat import org.oxycblt.musikr.cover.CoverFormat
import org.oxycblt.musikr.cover.MutableStoredCovers import org.oxycblt.musikr.cover.MutableStoredCovers
import org.oxycblt.musikr.cover.StoredCovers import org.oxycblt.musikr.cover.StoredCovers
import java.io.File
open class RevisionedStoredCovers(private val context: Context, private val revision: UUID?) : open class RevisionedStoredCovers(private val context: Context, private val revision: UUID?) :
StoredCovers { StoredCovers {
@ -48,6 +51,13 @@ open class RevisionedStoredCovers(private val context: Context, private val revi
return storedCovers.obtain(coverId)?.let { RevisionedCover(coverRevision, it) } 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) : class MutableRevisionedStoredCovers(context: Context, private val revision: UUID) :