Fix update subscription returning stale data (#727)

In case a manga was already loaded via the data loader, the cached data will get used.
Due to this, the update status did not return the updated manga data, but instead, stale data
This commit is contained in:
schroda
2023-10-29 16:01:55 +01:00
committed by GitHub
parent 583a2f0fad
commit 912c340a01
2 changed files with 61 additions and 2 deletions

View File

@@ -41,6 +41,24 @@ class MangaType(
var lastFetchedAt: Long?, // todo var lastFetchedAt: Long?, // todo
var chaptersLastFetchedAt: Long?, // todo var chaptersLastFetchedAt: Long?, // todo
) : Node { ) : Node {
companion object {
fun clearCacheFor(
mangaId: Int,
dataFetchingEnvironment: DataFetchingEnvironment,
) {
dataFetchingEnvironment.getDataLoader<List<Int>, MangaNodeList>("MangaDataLoader").clear(listOf(mangaId))
dataFetchingEnvironment.getDataLoader<List<Int>, MangaNodeList>("MangaForIdsDataLoader").clear(listOf(mangaId))
dataFetchingEnvironment.getDataLoader<Int, Int>("DownloadedChapterCountForMangaDataLoader").clear(mangaId)
dataFetchingEnvironment.getDataLoader<Int, Int>("UnreadChapterCountForMangaDataLoader").clear(mangaId)
dataFetchingEnvironment.getDataLoader<Int, Int>("LastReadChapterForMangaDataLoader").clear(mangaId)
dataFetchingEnvironment.getDataLoader<Int, ChapterNodeList>(
"ChaptersForMangaDataLoader",
).clear(mangaId)
dataFetchingEnvironment.getDataLoader<Int, Int>("MangaMetaDataLoader").clear(mangaId)
dataFetchingEnvironment.getDataLoader<Int, Int>("CategoriesForMangaDataLoader").clear(mangaId)
}
}
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
row[MangaTable.id].value, row[MangaTable.id].value,
row[MangaTable.sourceReference], row[MangaTable.sourceReference],

View File

@@ -8,6 +8,8 @@ import suwayomi.tachidesk.manga.impl.update.JobStatus
import suwayomi.tachidesk.manga.impl.update.UpdateStatus import suwayomi.tachidesk.manga.impl.update.UpdateStatus
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
private val jobStatusToMangaIdsToCacheClearedStatus = mutableMapOf<JobStatus, MutableMap<Int, Boolean>>()
class UpdateStatus( class UpdateStatus(
val isRunning: Boolean, val isRunning: Boolean,
val skippedCategories: UpdateStatusCategoryType, val skippedCategories: UpdateStatusCategoryType,
@@ -24,8 +26,22 @@ class UpdateStatus(
updatingCategories = UpdateStatusCategoryType(status.categoryStatusMap[CategoryUpdateStatus.UPDATING]?.map { it.id }.orEmpty()), updatingCategories = UpdateStatusCategoryType(status.categoryStatusMap[CategoryUpdateStatus.UPDATING]?.map { it.id }.orEmpty()),
pendingJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.PENDING]?.map { it.id }.orEmpty()), pendingJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.PENDING]?.map { it.id }.orEmpty()),
runningJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()), runningJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()),
completeJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.COMPLETE]?.map { it.id }.orEmpty()), completeJobs =
failedJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.FAILED]?.map { it.id }.orEmpty()), UpdateStatusType(
status.mangaStatusMap[JobStatus.COMPLETE]?.map {
it.id
}.orEmpty(),
JobStatus.COMPLETE,
status.running,
true,
),
failedJobs =
UpdateStatusType(
status.mangaStatusMap[JobStatus.FAILED]?.map { it.id }.orEmpty(),
JobStatus.FAILED,
status.running,
true,
),
skippedJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.SKIPPED]?.map { it.id }.orEmpty()), skippedJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.SKIPPED]?.map { it.id }.orEmpty()),
) )
} }
@@ -42,8 +58,33 @@ class UpdateStatusCategoryType(
class UpdateStatusType( class UpdateStatusType(
@get:GraphQLIgnore @get:GraphQLIgnore
val mangaIds: List<Int>, val mangaIds: List<Int>,
private val jobStatus: JobStatus? = null,
private val isRunning: Boolean = false,
private val clearCache: Boolean = false,
) { ) {
fun mangas(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> { fun mangas(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> {
val resetClearedMangaIds = !isRunning && clearCache && jobStatus != null
if (resetClearedMangaIds) {
jobStatusToMangaIdsToCacheClearedStatus[jobStatus]?.clear()
}
if (isRunning && clearCache && jobStatus != null) {
val cacheClearedForMangaIds =
jobStatusToMangaIdsToCacheClearedStatus.getOrPut(
jobStatus,
) { emptyMap<Int, Boolean>().toMutableMap() }
mangaIds.forEach {
if (cacheClearedForMangaIds[it] == true) {
return@forEach
}
MangaType.clearCacheFor(it, dataFetchingEnvironment)
cacheClearedForMangaIds[it] = true
}
}
return dataFetchingEnvironment.getValueFromDataLoader<List<Int>, MangaNodeList>("MangaForIdsDataLoader", mangaIds) return dataFetchingEnvironment.getValueFromDataLoader<List<Int>, MangaNodeList>("MangaForIdsDataLoader", mangaIds)
} }
} }