Fix deadlocks in gallery adder, favorites sync and backup/restore

This commit is contained in:
NerdNumber9 2019-04-14 18:20:22 -04:00
parent 24e10d6037
commit 6951ce34c7
3 changed files with 29 additions and 22 deletions

View File

@ -46,11 +46,13 @@ interface LewdSource<M : RaisedSearchMetadata, I> : CatalogueSource {
fun parseToManga(manga: SManga, input: I): Completable {
val mangaId = (manga as? Manga)?.id
val metaObservable = if(mangaId != null) {
db.getFlatMetadataForManga(mangaId).asRxSingle()
.map {
if(it != null) it.raise(metaClass)
else newMetaInstance()
}
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
Single.fromCallable {
db.getFlatMetadataForManga(mangaId).executeAsBlocking()
} .map {
if(it != null) it.raise(metaClass)
else newMetaInstance()
}
} else {
Single.just(newMetaInstance())
}
@ -76,10 +78,12 @@ interface LewdSource<M : RaisedSearchMetadata, I> : CatalogueSource {
*/
fun getOrLoadMetadata(mangaId: Long?, inputProducer: () -> Single<I>): Single<M> {
val metaObservable = if(mangaId != null) {
db.getFlatMetadataForManga(mangaId).asRxSingle()
.map {
it?.raise(metaClass)
}
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
Single.fromCallable {
db.getFlatMetadataForManga(mangaId).executeAsBlocking()
}.map {
it?.raise(metaClass)
}
} else Single.just(null)
return metaObservable.flatMap { existingMeta ->

View File

@ -3,6 +3,7 @@ package exh.favorites
import android.content.Context
import android.net.wifi.WifiManager
import android.os.PowerManager
import com.elvishew.xlog.XLog
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
@ -21,7 +22,6 @@ import exh.util.trans
import okhttp3.FormBody
import okhttp3.Request
import rx.subjects.BehaviorSubject
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -47,6 +47,8 @@ class FavoritesSyncHelper(val context: Context) {
private var wifiLock: WifiManager.WifiLock? = null
private var wakeLock: PowerManager.WakeLock? = null
private val logger = XLog.tag("EHFavSync").build()
val status = BehaviorSubject.create<FavoritesSyncStatus>(FavoritesSyncStatus.Idle())
@Synchronized
@ -73,7 +75,7 @@ class FavoritesSyncHelper(val context: Context) {
exh.fetchFavorites()
} catch(e: Exception) {
status.onNext(FavoritesSyncStatus.Error("Failed to fetch favorites from remote server!"))
Timber.e(e, "Could not fetch favorites!")
logger.e( "Could not fetch favorites!", e)
return
}
@ -125,11 +127,11 @@ class FavoritesSyncHelper(val context: Context) {
}
} catch(e: IgnoredException) {
//Do not display error as this error has already been reported
Timber.w(e, "Ignoring exception!")
logger.w( "Ignoring exception!", e)
return
} catch (e: Exception) {
status.onNext(FavoritesSyncStatus.Error("Unknown error: ${e.message}"))
Timber.e(e, "Sync error!")
logger.e( "Sync error!", e)
return
} finally {
//Release wake + wifi locks
@ -228,7 +230,7 @@ class FavoritesSyncHelper(val context: Context) {
break
}
} catch (e: Exception) {
Timber.e(e, "Sync network error!")
logger.w( "Sync network error!", e)
}
}
@ -381,7 +383,7 @@ sealed class FavoritesSyncStatus(val message: String) {
class Idle : FavoritesSyncStatus("Waiting for sync to start")
class Initializing : FavoritesSyncStatus("Initializing sync")
class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(if(isThrottle)
(message + "\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete.")
"$message\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete."
else
message)
class CompleteWithErrors(messages: List<String>) : FavoritesSyncStatus(messages.joinToString("\n"))

View File

@ -24,14 +24,15 @@ data class FlatMetadata(
}
fun DatabaseHelper.getFlatMetadataForManga(mangaId: Long): PreparedOperation<FlatMetadata?> {
fun getSingle() = getSearchMetadataForManga(mangaId).asRxSingle().flatMap { meta ->
if(meta == null) Single.just(null)
else Single.zip(
getSearchTagsForManga(mangaId).asRxSingle(),
getSearchTitlesForManga(mangaId).asRxSingle()
) { tags, titles ->
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
fun getSingle() = Single.fromCallable {
val meta = getSearchMetadataForManga(mangaId).executeAsBlocking()
if(meta != null) {
val tags = getSearchTagsForManga(mangaId).executeAsBlocking()
val titles = getSearchTitlesForManga(mangaId).executeAsBlocking()
FlatMetadata(meta, tags, titles)
}
} else null
}
return object : PreparedOperation<FlatMetadata?> {