Ignore non-existent galleries during favorites sync

This commit is contained in:
NerdNumber9 2019-04-14 18:53:34 -04:00
parent 98ac8a69c2
commit 77c07d13c0
5 changed files with 47 additions and 20 deletions

View File

@ -10,7 +10,11 @@ import rx.Producer
import rx.Subscription
import java.util.concurrent.atomic.AtomicBoolean
fun Call.asObservable(): Observable<Response> {
fun Call.asObservableWithAsyncStacktrace(): Observable<Pair<Exception, Response>> {
// Record stacktrace at creation time for easier debugging
// asObservable is involved in a lot of crashes so this is worth the performance hit
val asyncStackTrace = Exception("Async stacktrace")
return Observable.unsafeCreate { subscriber ->
// Since Call is a one-shot type, clone it for each new subscriber.
val call = clone()
@ -23,12 +27,12 @@ fun Call.asObservable(): Observable<Response> {
try {
val response = call.execute()
if (!subscriber.isUnsubscribed) {
subscriber.onNext(response)
subscriber.onNext(asyncStackTrace to response)
subscriber.onCompleted()
}
} catch (error: Exception) {
if (!subscriber.isUnsubscribed) {
subscriber.onError(error)
subscriber.onError(error.withRootCause(asyncStackTrace))
}
}
}
@ -47,19 +51,14 @@ fun Call.asObservable(): Observable<Response> {
}
}
fun Call.asObservableSuccess(): Observable<Response> {
// Record stacktrace at creation time for easier debugging
// asObservable is involved in a lot of crashes so this is worth the performance hit
val asyncStackTrace = Exception("Async stacktrace")
fun Call.asObservable() = asObservableWithAsyncStacktrace().map { it.second }
return asObservable().doOnNext { response ->
fun Call.asObservableSuccess(): Observable<Response> {
return asObservableWithAsyncStacktrace().map { (asyncStacktrace, response) ->
if (!response.isSuccessful) {
response.close()
throw Exception("HTTP error ${response.code()}")
}
}.onErrorReturn {
// Set root cause to async stacktrace and throw again
throw it.withRootCause(asyncStackTrace)
throw Exception("HTTP error ${response.code()}", asyncStacktrace)
} else response
}
}

View File

@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace
import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.LewdSource
@ -32,6 +33,7 @@ import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
import java.util.*
import exh.metadata.metadata.base.RaisedTag
import java.lang.RuntimeException
class EHentai(override val id: Long,
val exh: Boolean,
@ -236,11 +238,21 @@ class EHentai(override val id: Long,
*/
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return client.newCall(mangaDetailsRequest(manga))
.asObservableSuccess()
.flatMap {
parseToManga(manga, it).andThen(Observable.just(manga.apply {
initialized = true
}))
.asObservableWithAsyncStacktrace()
.flatMap { (stacktrace, response) ->
if(response.isSuccessful) {
parseToManga(manga, response).andThen(Observable.just(manga.apply {
initialized = true
}))
} else {
response.close()
if(response.code() == 404) {
throw GalleryNotFoundException(stacktrace)
} else {
throw Exception("HTTP error ${response.code()}", stacktrace)
}
}
}
}
@ -522,6 +534,8 @@ class EHentai(override val id: Long,
else
"E-Hentai"
class GalleryNotFoundException(cause: Throwable): RuntimeException("Gallery not found!", cause)
companion object {
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
private const val TR_SUFFIX = "TR"

View File

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.util.syncChaptersWithSource
import exh.metadata.metadata.EHentaiSearchMetadata
import okhttp3.MediaType
@ -186,6 +187,11 @@ class GalleryAdder {
return GalleryAddEvent.Success(url, manga)
} catch(e: Exception) {
XLog.w("Could not add gallery!", e)
if(e is EHentai.GalleryNotFoundException) {
return GalleryAddEvent.Fail.NotFound(url)
}
return GalleryAddEvent.Fail.Error(url,
((e.message ?: "Unknown error!") + " (Gallery: $url)").trim())
}
@ -223,7 +229,10 @@ sealed class GalleryAddEvent {
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
}
class Error(override val galleryUrl: String,
open class Error(override val galleryUrl: String,
override val logMessage: String): Fail()
class NotFound(galleryUrl: String):
Error(galleryUrl, "Gallery does not exist: $galleryUrl")
}
}

View File

@ -323,6 +323,12 @@ class FavoritesSyncHelper(val context: Context) {
EXH_SOURCE_ID)
if(result is GalleryAddEvent.Fail) {
if(result is GalleryAddEvent.Fail.NotFound) {
XLog.e("Remote gallery does not exist, skipping: %s!", it.getUrl())
// Skip this gallery, it no longer exists
return@forEachIndexed
}
val errorString = "Failed to add gallery to local database: " + when (result) {
is GalleryAddEvent.Fail.Error -> "'${it.title}' ${result.logMessage}"
is GalleryAddEvent.Fail.UnknownType -> "'${it.title}' (${result.galleryUrl}) is not a valid gallery!"

View File

@ -43,7 +43,6 @@ class BatchAddPresenter: BasePresenter<BatchAddController>() {
eventRelay?.call((when (result) {
is GalleryAddEvent.Success -> "[OK]"
is GalleryAddEvent.Fail -> "[ERROR]"
else -> "[???]"
}) + " " + result.logMessage)
}