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:
+5
-2
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user