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
@@ -41,6 +41,24 @@ class MangaType(
var lastFetchedAt: Long?, // todo
var chaptersLastFetchedAt: Long?, // todo
) : 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(
row[MangaTable.id].value,
row[MangaTable.sourceReference],
@@ -8,6 +8,8 @@ import suwayomi.tachidesk.manga.impl.update.JobStatus
import suwayomi.tachidesk.manga.impl.update.UpdateStatus
import java.util.concurrent.CompletableFuture
private val jobStatusToMangaIdsToCacheClearedStatus = mutableMapOf<JobStatus, MutableMap<Int, Boolean>>()
class UpdateStatus(
val isRunning: Boolean,
val skippedCategories: UpdateStatusCategoryType,
@@ -24,8 +26,22 @@ class UpdateStatus(
updatingCategories = UpdateStatusCategoryType(status.categoryStatusMap[CategoryUpdateStatus.UPDATING]?.map { it.id }.orEmpty()),
pendingJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.PENDING]?.map { it.id }.orEmpty()),
runningJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()),
completeJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.COMPLETE]?.map { it.id }.orEmpty()),
failedJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.FAILED]?.map { it.id }.orEmpty()),
completeJobs =
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()),
)
}
@@ -42,8 +58,33 @@ class UpdateStatusCategoryType(
class UpdateStatusType(
@get:GraphQLIgnore
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> {
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)
}
}