Fix page previews cache

This commit is contained in:
Jobobby04 2023-10-27 17:14:38 -04:00
parent d45563e58d
commit d600ddc11a
6 changed files with 108 additions and 59 deletions

View File

@ -26,7 +26,7 @@ android {
defaultConfig {
applicationId = "eu.kanade.tachiyomi.sy"
versionCode = 57
versionCode = 58
versionName = "1.9.3"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")

View File

@ -6,12 +6,13 @@ import com.jakewharton.disklrucache.DiskLruCache
import eu.kanade.tachiyomi.source.PagePreviewPage
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.saveTo
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.Response
import logcat.LogPriority
import okio.Source
import okio.buffer
import okio.sink
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.injectLazy
import java.io.File
@ -159,7 +160,7 @@ class PagePreviewCache(private val context: Context) {
* @throws IOException page error.
*/
@Throws(IOException::class)
fun putImageToCache(imageUrl: String, response: Response) {
fun putImageToCache(imageUrl: String, source: Source) {
// Initialize editor (edits the values for an entry).
var editor: DiskLruCache.Editor? = null
@ -169,12 +170,12 @@ class PagePreviewCache(private val context: Context) {
editor = diskCache.edit(key) ?: throw IOException("Unable to edit key")
// Get OutputStream and write page with Okio.
response.body.source().saveTo(editor.newOutputStream(0))
source.buffer().saveTo(editor.newOutputStream(0))
diskCache.flush()
editor.commit()
} finally {
response.body.close()
source.close()
editor?.abortUnlessCommitted()
}
}
@ -207,6 +208,7 @@ class PagePreviewCache(private val context: Context) {
// Remove file from cache.
diskCache.remove(key)
} catch (e: Exception) {
logcat(LogPriority.WARN, e) { "Failed to remove file from cache" }
false
}
}

View File

@ -23,8 +23,6 @@ import okhttp3.Response
import okhttp3.internal.http.HTTP_NOT_MODIFIED
import okio.Path.Companion.toOkioPath
import okio.Source
import okio.buffer
import okio.sink
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.injectLazy
@ -39,7 +37,9 @@ import java.io.File
class PagePreviewFetcher(
private val page: PagePreview,
private val options: Options,
private val pagePreviewFileLazy: Lazy<File>,
private val pagePreviewFile: () -> File,
private val isInCache: () -> Boolean,
private val writeToCache: (Source) -> Unit,
private val diskCacheKeyLazy: Lazy<String>,
private val sourceLazy: Lazy<PagePreviewSource?>,
private val callFactoryLazy: Lazy<Call.Factory>,
@ -62,14 +62,14 @@ class PagePreviewFetcher(
}
private suspend fun httpLoader(): FetchResult {
if (pagePreviewFileLazy.value.exists() && options.diskCachePolicy.readEnabled) {
return fileLoader(pagePreviewFileLazy.value)
if (isInCache() && options.diskCachePolicy.readEnabled) {
return fileLoader(pagePreviewFile())
}
var snapshot = readFromDiskCache()
try {
// Fetch from disk cache
if (snapshot != null) {
val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot, pagePreviewFileLazy.value)
val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot)
if (snapshotPagePreviewCache != null) {
// Read from page preview cache
return fileLoader(snapshotPagePreviewCache)
@ -88,7 +88,7 @@ class PagePreviewFetcher(
val responseBody = checkNotNull(response.body) { "Null response source" }
try {
// Read from page preview cache after page preview updated
val responsePagePreviewCache = writeResponseToPagePreviewCache(response, pagePreviewFileLazy.value)
val responsePagePreviewCache = writeResponseToPagePreviewCache(response)
if (responsePagePreviewCache != null) {
return fileLoader(responsePagePreviewCache)
}
@ -153,60 +153,59 @@ class PagePreviewFetcher(
return request.build()
}
private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot, cacheFile: File): File? {
private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot): File? {
return try {
diskCacheLazy.value.run {
fileSystem.source(snapshot.data).use { input ->
writeSourceToPagePreviewCache(input, cacheFile)
writeSourceToPagePreviewCache(input)
}
remove(diskCacheKey)
}
cacheFile.takeIf { it.exists() }
return if (isInCache()) {
pagePreviewFile()
} else {
null
}
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache ${cacheFile.name}" }
logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache $diskCacheKey" }
null
}
}
private fun writeResponseToPagePreviewCache(response: Response, cacheFile: File): File? {
private fun writeResponseToPagePreviewCache(response: Response): File? {
if (!options.diskCachePolicy.writeEnabled) return null
return try {
response.peekBody(Long.MAX_VALUE).source().use { input ->
writeSourceToPagePreviewCache(input, cacheFile)
writeSourceToPagePreviewCache(input)
}
return if (isInCache()) {
pagePreviewFile()
} else {
null
}
cacheFile.takeIf { it.exists() }
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache ${cacheFile.name}" }
logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache $diskCacheKey" }
null
}
}
private fun writeSourceToPagePreviewCache(input: Source, cacheFile: File) {
cacheFile.parentFile?.mkdirs()
cacheFile.delete()
try {
cacheFile.sink().buffer().use { output ->
output.writeAll(input)
}
} catch (e: Exception) {
cacheFile.delete()
throw e
}
private fun writeSourceToPagePreviewCache(input: Source) {
writeToCache(input)
}
private fun readFromDiskCache(): DiskCache.Snapshot? {
return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey] else null
return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value.openSnapshot(diskCacheKey) else null
}
private fun writeToDiskCache(
response: Response,
): DiskCache.Snapshot? {
val editor = diskCacheLazy.value.edit(diskCacheKey) ?: return null
val editor = diskCacheLazy.value.openEditor(diskCacheKey) ?: return null
try {
diskCacheLazy.value.fileSystem.write(editor.data) {
response.body.source().readAll(this)
}
return editor.commitAndGet()
return editor.commitAndOpenSnapshot()
} catch (e: Exception) {
try {
editor.abort()
@ -232,7 +231,9 @@ class PagePreviewFetcher(
return PagePreviewFetcher(
page = data,
options = options,
pagePreviewFileLazy = lazy { pagePreviewCache.getImageFile(data.imageUrl) },
pagePreviewFile = { pagePreviewCache.getImageFile(data.imageUrl) },
isInCache = { pagePreviewCache.isImageInCache(data.imageUrl) },
writeToCache = { pagePreviewCache.putImageToCache(data.imageUrl, it) },
diskCacheKeyLazy = lazy { PagePreviewKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? PagePreviewSource },
callFactoryLazy = callFactoryLazy,

View File

@ -173,6 +173,7 @@ class MainActivity : BaseActivity() {
readerPreferences = Injekt.get(),
backupPreferences = Injekt.get(),
trackerManager = Injekt.get(),
pagePreviewCache = Injekt.get(),
)
} else {
false

View File

@ -10,6 +10,7 @@ import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkPreferences
@ -39,6 +40,7 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive
import logcat.LogPriority
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.TriState
import tachiyomi.core.preference.getAndSet
@ -99,6 +101,7 @@ object EXHMigrations {
readerPreferences: ReaderPreferences,
backupPreferences: BackupPreferences,
trackerManager: TrackerManager,
pagePreviewCache: PagePreviewCache,
): Boolean {
val lastVersionCode = preferenceStore.getInt("eh_last_version_code", 0)
val oldVersion = lastVersionCode.get()
@ -559,6 +562,20 @@ object EXHMigrations {
uiPreferences.relativeTime().set(false)
}
}
if (oldVersion under 58) {
pagePreviewCache.clear()
File(context.cacheDir, PagePreviewCache.PARAMETER_CACHE_DIRECTORY).listFiles()?.forEach {
if (it.name == "journal" || it.name.startsWith("journal.")) {
return@forEach
}
try {
it.delete()
} catch (e: Exception) {
logcat(LogPriority.WARN, e) { "Failed to remove file from cache" }
}
}
}
// if (oldVersion under 1) { } (1 is current release version)
// do stuff here when releasing changed crap

View File

@ -8,6 +8,7 @@ import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.AndroidSourceManager
@ -40,37 +41,64 @@ import java.util.UUID
@Suppress("unused")
object DebugFunctions {
val app: Application by injectLazy()
val handler: DatabaseHandler by injectLazy()
val prefsStore: PreferenceStore by injectLazy()
val basePrefs: BasePreferences by injectLazy()
val uiPrefs: UiPreferences by injectLazy()
val networkPrefs: NetworkPreferences by injectLazy()
val sourcePrefs: SourcePreferences by injectLazy()
val securityPrefs: SecurityPreferences by injectLazy()
val libraryPrefs: LibraryPreferences by injectLazy()
val readerPrefs: ReaderPreferences by injectLazy()
val backupPrefs: BackupPreferences by injectLazy()
val trackerManager: TrackerManager by injectLazy()
val sourceManager: SourceManager by injectLazy()
val updateManga: UpdateManga by injectLazy()
val getFavorites: GetFavorites by injectLazy()
val getFlatMetadataById: GetFlatMetadataById by injectLazy()
val insertFlatMetadata: InsertFlatMetadata by injectLazy()
val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy()
val getSearchMetadata: GetSearchMetadata by injectLazy()
val getAllManga: GetAllManga by injectLazy()
private val app: Application by injectLazy()
private val handler: DatabaseHandler by injectLazy()
private val prefsStore: PreferenceStore by injectLazy()
private val basePrefs: BasePreferences by injectLazy()
private val uiPrefs: UiPreferences by injectLazy()
private val networkPrefs: NetworkPreferences by injectLazy()
private val sourcePrefs: SourcePreferences by injectLazy()
private val securityPrefs: SecurityPreferences by injectLazy()
private val libraryPrefs: LibraryPreferences by injectLazy()
private val readerPrefs: ReaderPreferences by injectLazy()
private val backupPrefs: BackupPreferences by injectLazy()
private val trackerManager: TrackerManager by injectLazy()
private val sourceManager: SourceManager by injectLazy()
private val updateManga: UpdateManga by injectLazy()
private val getFavorites: GetFavorites by injectLazy()
private val getFlatMetadataById: GetFlatMetadataById by injectLazy()
private val insertFlatMetadata: InsertFlatMetadata by injectLazy()
private val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy()
private val getSearchMetadata: GetSearchMetadata by injectLazy()
private val getAllManga: GetAllManga by injectLazy()
private val pagePreviewCache: PagePreviewCache by injectLazy()
fun forceUpgradeMigration() {
val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0)
lastVersionCode.set(1)
EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs, trackerManager)
EXHMigrations.upgrade(
context = app,
preferenceStore = prefsStore,
basePreferences = basePrefs,
uiPreferences = uiPrefs,
networkPreferences = networkPrefs,
sourcePreferences = sourcePrefs,
securityPreferences = securityPrefs,
libraryPreferences = libraryPrefs,
readerPreferences = readerPrefs,
backupPreferences = backupPrefs,
trackerManager = trackerManager,
pagePreviewCache = pagePreviewCache,
)
}
fun forceSetupJobs() {
val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0)
lastVersionCode.set(0)
EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs, trackerManager)
EXHMigrations.upgrade(
context = app,
preferenceStore = prefsStore,
basePreferences = basePrefs,
uiPreferences = uiPrefs,
networkPreferences = networkPrefs,
sourcePreferences = sourcePrefs,
securityPreferences = securityPrefs,
libraryPreferences = libraryPrefs,
readerPreferences = readerPrefs,
backupPreferences = backupPrefs,
trackerManager = trackerManager,
pagePreviewCache = pagePreviewCache,
)
}
fun resetAgedFlagInEXHManga() {
@ -190,7 +218,7 @@ object DebugFunctions {
"""
{
id: ${info.id},
isPeriodic: ${j.extras["EXTRA_IS_PERIODIC"]},
isPeriodic: ${j.extras.getBoolean("EXTRA_IS_PERIODIC")},
state: ${info.state.name},
tags: [
${info.tags.joinToString(separator = ",\n ")}