Fix next expected update being weird number sometimes

Occurs if manga.lastUpdate has never been set yet.
This commit is contained in:
arkon 2024-01-01 18:32:21 -05:00
parent ec478cbb1b
commit 22589a9c30
3 changed files with 24 additions and 35 deletions

View file

@ -22,7 +22,6 @@ import tachiyomi.domain.chapter.service.ChapterRecognition
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import java.lang.Long.max import java.lang.Long.max
import java.time.Instant
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.TreeSet import java.util.TreeSet
@ -57,6 +56,7 @@ class SyncChaptersWithSource(
} }
val now = ZonedDateTime.now() val now = ZonedDateTime.now()
val nowMillis = now.toInstant().toEpochMilli()
val sourceChapters = rawSourceChapters val sourceChapters = rawSourceChapters
.distinctBy { it.url } .distinctBy { it.url }
@ -67,36 +67,27 @@ class SyncChaptersWithSource(
.copy(mangaId = manga.id, sourceOrder = i.toLong()) .copy(mangaId = manga.id, sourceOrder = i.toLong())
} }
// Chapters from db.
val dbChapters = getChaptersByMangaId.await(manga.id) val dbChapters = getChaptersByMangaId.await(manga.id)
// Chapters from the source not in db. val newChapters = mutableListOf<Chapter>()
val toAdd = mutableListOf<Chapter>() val updatedChapters = mutableListOf<Chapter>()
val removedChapters = dbChapters.filterNot { dbChapter ->
// Chapters whose metadata have changed.
val toChange = mutableListOf<Chapter>()
// Chapters from the db not in source.
val toDelete = dbChapters.filterNot { dbChapter ->
sourceChapters.any { sourceChapter -> sourceChapters.any { sourceChapter ->
dbChapter.url == sourceChapter.url dbChapter.url == sourceChapter.url
} }
} }
val rightNow = Instant.now().toEpochMilli()
// Used to not set upload date of older chapters // Used to not set upload date of older chapters
// to a higher value than newer chapters // to a higher value than newer chapters
var maxSeenUploadDate = 0L var maxSeenUploadDate = 0L
val sManga = manga.toSManga()
for (sourceChapter in sourceChapters) { for (sourceChapter in sourceChapters) {
var chapter = sourceChapter var chapter = sourceChapter
// Update metadata from source if necessary. // Update metadata from source if necessary.
if (source is HttpSource) { if (source is HttpSource) {
val sChapter = chapter.toSChapter() val sChapter = chapter.toSChapter()
source.prepareNewChapter(sChapter, sManga) source.prepareNewChapter(sChapter, manga.toSManga())
chapter = chapter.copyFromSChapter(sChapter) chapter = chapter.copyFromSChapter(sChapter)
} }
@ -108,13 +99,13 @@ class SyncChaptersWithSource(
if (dbChapter == null) { if (dbChapter == null) {
val toAddChapter = if (chapter.dateUpload == 0L) { val toAddChapter = if (chapter.dateUpload == 0L) {
val altDateUpload = if (maxSeenUploadDate == 0L) rightNow else maxSeenUploadDate val altDateUpload = if (maxSeenUploadDate == 0L) nowMillis else maxSeenUploadDate
chapter.copy(dateUpload = altDateUpload) chapter.copy(dateUpload = altDateUpload)
} else { } else {
maxSeenUploadDate = max(maxSeenUploadDate, sourceChapter.dateUpload) maxSeenUploadDate = max(maxSeenUploadDate, sourceChapter.dateUpload)
chapter chapter
} }
toAdd.add(toAddChapter) newChapters.add(toAddChapter)
} else { } else {
if (shouldUpdateDbChapter.await(dbChapter, chapter)) { if (shouldUpdateDbChapter.await(dbChapter, chapter)) {
val shouldRenameChapter = downloadProvider.isChapterDirNameChanged(dbChapter, chapter) && val shouldRenameChapter = downloadProvider.isChapterDirNameChanged(dbChapter, chapter) &&
@ -134,13 +125,13 @@ class SyncChaptersWithSource(
if (chapter.dateUpload != 0L) { if (chapter.dateUpload != 0L) {
toChangeChapter = toChangeChapter.copy(dateUpload = chapter.dateUpload) toChangeChapter = toChangeChapter.copy(dateUpload = chapter.dateUpload)
} }
toChange.add(toChangeChapter) updatedChapters.add(toChangeChapter)
} }
} }
} }
// Return if there's nothing to add, delete or change, avoiding unnecessary db transactions. // Return if there's nothing to add, delete, or update to avoid unnecessary db transactions.
if (toAdd.isEmpty() && toDelete.isEmpty() && toChange.isEmpty()) { if (newChapters.isEmpty() && removedChapters.isEmpty() && updatedChapters.isEmpty()) {
if (manualFetch || manga.fetchInterval == 0 || manga.nextUpdate < fetchWindow.first) { if (manualFetch || manga.fetchInterval == 0 || manga.nextUpdate < fetchWindow.first) {
updateManga.awaitUpdateFetchInterval( updateManga.awaitUpdateFetchInterval(
manga, manga,
@ -157,20 +148,20 @@ class SyncChaptersWithSource(
val deletedReadChapterNumbers = TreeSet<Double>() val deletedReadChapterNumbers = TreeSet<Double>()
val deletedBookmarkedChapterNumbers = TreeSet<Double>() val deletedBookmarkedChapterNumbers = TreeSet<Double>()
toDelete.forEach { chapter -> removedChapters.forEach { chapter ->
if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber) if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber)
if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber) if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber)
deletedChapterNumbers.add(chapter.chapterNumber) deletedChapterNumbers.add(chapter.chapterNumber)
} }
val deletedChapterNumberDateFetchMap = toDelete.sortedByDescending { it.dateFetch } val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch }
.associate { it.chapterNumber to it.dateFetch } .associate { it.chapterNumber to it.dateFetch }
// Date fetch is set in such a way that the upper ones will have bigger value than the lower ones // Date fetch is set in such a way that the upper ones will have bigger value than the lower ones
// Sources MUST return the chapters from most to less recent, which is common. // Sources MUST return the chapters from most to less recent, which is common.
var itemCount = toAdd.size var itemCount = newChapters.size
var updatedToAdd = toAdd.map { toAddItem -> var updatedToAdd = newChapters.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = rightNow + itemCount--) var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--)
if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
@ -189,8 +180,8 @@ class SyncChaptersWithSource(
chapter chapter
} }
if (toDelete.isNotEmpty()) { if (removedChapters.isNotEmpty()) {
val toDeleteIds = toDelete.map { it.id } val toDeleteIds = removedChapters.map { it.id }
chapterRepository.removeChaptersWithIds(toDeleteIds) chapterRepository.removeChaptersWithIds(toDeleteIds)
} }
@ -198,8 +189,8 @@ class SyncChaptersWithSource(
updatedToAdd = chapterRepository.addAll(updatedToAdd) updatedToAdd = chapterRepository.addAll(updatedToAdd)
} }
if (toChange.isNotEmpty()) { if (updatedChapters.isNotEmpty()) {
val chapterUpdates = toChange.map { it.toChapterUpdate() } val chapterUpdates = updatedChapters.map { it.toChapterUpdate() }
updateChapter.awaitAll(chapterUpdates) updateChapter.awaitAll(chapterUpdates)
} }
updateManga.awaitUpdateFetchInterval(manga, now, fetchWindow) updateManga.awaitUpdateFetchInterval(manga, now, fetchWindow)

View file

@ -77,7 +77,6 @@ fun SetIntervalDialog(
title = { Text(stringResource(MR.strings.manga_modify_calculated_interval_title)) }, title = { Text(stringResource(MR.strings.manga_modify_calculated_interval_title)) },
text = { text = {
Column { Column {
// TODO: figure out why nextUpdate is a weird number sometimes
if (nextUpdateDays >= 0) { if (nextUpdateDays >= 0) {
Text( Text(
stringResource( stringResource(

View file

@ -19,16 +19,15 @@ class FetchInterval(
dateTime: ZonedDateTime, dateTime: ZonedDateTime,
window: Pair<Long, Long>, window: Pair<Long, Long>,
): MangaUpdate? { ): MangaUpdate? {
val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(
chapters = getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true),
zone = dateTime.zone,
)
val currentWindow = if (window.first == 0L && window.second == 0L) { val currentWindow = if (window.first == 0L && window.second == 0L) {
getWindow(ZonedDateTime.now()) getWindow(ZonedDateTime.now())
} else { } else {
window window
} }
val chapters = getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true)
val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(
chapters,
dateTime.zone,
)
val nextUpdate = calculateNextUpdate(manga, interval, dateTime, currentWindow) val nextUpdate = calculateNextUpdate(manga, interval, dateTime, currentWindow)
return if (manga.nextUpdate == nextUpdate && manga.fetchInterval == interval) { return if (manga.nextUpdate == nextUpdate && manga.fetchInterval == interval) {
@ -102,7 +101,7 @@ class FetchInterval(
manga.fetchInterval == 0 manga.fetchInterval == 0
) { ) {
val latestDate = ZonedDateTime.ofInstant( val latestDate = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(manga.lastUpdate), if (manga.lastUpdate > 0) Instant.ofEpochMilli(manga.lastUpdate) else Instant.now(),
dateTime.zone, dateTime.zone,
) )
.toLocalDate() .toLocalDate()