Reapply "Fix cache invalidation isn't done at startup (#2970)"

This reverts commit d219c5e3bbcfb24c40fa69e40bff11b6fd81fd7f.

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt
This commit is contained in:
AntsyLich
2026-02-26 18:43:03 +06:00
committed by Jobobby04
parent 9c01119d24
commit c17e9573b7
2 changed files with 42 additions and 15 deletions
@@ -223,6 +223,7 @@ object SettingsAdvancedScreen : SearchableSettings {
private fun getDataGroup(): Preference.PreferenceGroup {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow
val scope = rememberCoroutineScope()
return Preference.PreferenceGroup(
title = stringResource(MR.strings.label_data),
@@ -231,8 +232,10 @@ object SettingsAdvancedScreen : SearchableSettings {
title = stringResource(MR.strings.pref_invalidate_download_cache),
subtitle = stringResource(MR.strings.pref_invalidate_download_cache_summary),
onClick = {
Injekt.get<DownloadCache>().invalidateCache()
context.toast(MR.strings.download_cache_invalidated)
scope.launch {
Injekt.get<DownloadCache>().invalidateCache()
context.toast(MR.strings.download_cache_invalidated)
}
},
),
Preference.PreferenceItem.TextPreference(
@@ -12,14 +12,17 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
@@ -109,13 +112,19 @@ class DownloadCache(
ProtoBuf.decodeFromByteArray<RootDirectory>(it.readBytes())
}
rootDownloadsDir = diskCache
lastRenew = System.currentTimeMillis()
}
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e) { "Failed to initialize from disk cache" }
diskCacheFile.delete()
}
}
sourceManager.catalogueSources
.map { sources -> sources.map { it.id }.toSet() }
.distinctUntilChanged()
.collect {
restartRenewal()
}
}
storageManager.changes
@@ -353,19 +362,34 @@ class DownloadCache(
notifyChanges()
}
fun invalidateCache() {
lastRenew = 0L
renewalJob?.cancel()
suspend fun invalidateCache() {
renewalJob?.cancelAndJoin()
diskCacheFile.delete()
renewCache()
lastRenew = 0L
renewCache(forceRenew = true)
}
/**
* Safely cancels any in-progress renewal job, resets the last-renew timestamp, and
* immediately starts a new renewal, bypassing the time-based throttle.
*/
private fun restartRenewal() {
renewalJob?.cancel()
lastRenew = 0L
renewCache(forceRenew = true)
}
/**
* Renews the downloads cache.
*
* @param forceRenew when `true`, the time-based throttle is bypassed. Use this after
* explicitly cancelling the previous job to avoid a race where the cancelled job's
* [invokeOnCompletion] handler sets [lastRenew] after the reset but before the new
* job's guard check.
*/
private fun renewCache() {
private fun renewCache(forceRenew: Boolean = false) {
// Avoid renewing cache if in the process nor too often
if (lastRenew + renewInterval >= System.currentTimeMillis() || renewalJob?.isActive == true) {
if ((!forceRenew && lastRenew + renewInterval >= System.currentTimeMillis()) || renewalJob?.isActive == true) {
return
}
@@ -376,15 +400,14 @@ class DownloadCache(
// Try to wait until extensions and sources have loaded
// SY -->
var sources = emptyList<Source>()
withTimeoutOrNull(30.seconds) {
extensionManager.isInitialized.first { it }
sourceManager.isInitialized.first { it }
sources = getSources()
// SY <--
sourceManager.catalogueSources.first { it.isNotEmpty() }
// SY -->
}
// SY <--
val sources = getSources()
val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id }
rootDownloadsDirMutex.withLock {
@@ -459,8 +482,9 @@ class DownloadCache(
private var updateDiskCacheJob: Job? = null
private fun updateDiskCache() {
updateDiskCacheJob?.cancel()
val previousJob = updateDiskCacheJob
updateDiskCacheJob = scope.launchIO {
previousJob?.cancelAndJoin()
delay(1000)
ensureActive()
val bytes = ProtoBuf.encodeToByteArray(rootDownloadsDir)