Don't let the stored download index overwrite a startup rescan (#3968)

Closes #3968
Fixes #3526
Fixes #2808
Fixes #1429

Co-authored-by: Chopper <156493704+choppeh@users.noreply.github.com>
This commit is contained in:
AntsyLich
2026-10-10 17:36:20 +06:00
co-authored by Chopper
parent f28b2d887e
commit 88d4071cce
@@ -1,7 +1,9 @@
package eu.kanade.tachiyomi.data.download
import android.content.Context
import android.util.AtomicFile
import androidx.core.net.toUri
import androidx.core.util.writeBytes
import com.hippo.unifile.UniFile
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.Inject
@@ -25,7 +27,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withTimeoutOrNull
@@ -88,25 +89,26 @@ class DownloadCache(
*/
private var lastRenew = 0L
private var renewalJob: Job? = null
private val initJob: Job
private val _isInitializing = MutableStateFlow(false)
val isInitializing = _isInitializing
.debounce(1.seconds) // Don't notify if it finishes quickly enough
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
private val diskCacheFile: File
get() = File(context.cacheDir, "dl_index_cache_v3")
private val diskCacheFile: AtomicFile
get() = AtomicFile(File(context.cacheDir, "dl_index_cache_v3"))
private val rootDownloadsDirMutex = Mutex()
private var rootDownloadsDir = RootDirectory(storageManager.getDownloadsDirectory())
init {
// Attempt to read cache file
scope.launch {
initJob = scope.launchIO {
rootDownloadsDirMutex.withLock {
try {
if (diskCacheFile.exists()) {
val diskCache = diskCacheFile.inputStream().use {
if (diskCacheFile.baseFile.exists()) {
val diskCache = diskCacheFile.openRead().use {
ProtoBuf.decodeFromByteArray<RootDirectory>(it.readBytes())
}
rootDownloadsDir = diskCache
@@ -360,6 +362,9 @@ class DownloadCache(
}
renewalJob = scope.launchIO {
// The disk index is older than this scan and would replace it if read afterwards
initJob.join()
if (lastRenew == 0L) {
_isInitializing.emit(true)
}
@@ -445,8 +450,9 @@ class DownloadCache(
updateDiskCacheJob?.cancel()
updateDiskCacheJob = scope.launchIO {
delay(1.seconds)
ensureActive()
val bytes = ProtoBuf.encodeToByteArray(rootDownloadsDir)
val bytes = rootDownloadsDirMutex.withLock {
ProtoBuf.encodeToByteArray(rootDownloadsDir)
}
ensureActive()
try {
diskCacheFile.writeBytes(bytes)