Fix deadlocks in gallery adder, favorites sync and backup/restore
This commit is contained in:
parent
24e10d6037
commit
6951ce34c7
@ -46,11 +46,13 @@ interface LewdSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
fun parseToManga(manga: SManga, input: I): Completable {
|
fun parseToManga(manga: SManga, input: I): Completable {
|
||||||
val mangaId = (manga as? Manga)?.id
|
val mangaId = (manga as? Manga)?.id
|
||||||
val metaObservable = if(mangaId != null) {
|
val metaObservable = if(mangaId != null) {
|
||||||
db.getFlatMetadataForManga(mangaId).asRxSingle()
|
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
||||||
.map {
|
Single.fromCallable {
|
||||||
if(it != null) it.raise(metaClass)
|
db.getFlatMetadataForManga(mangaId).executeAsBlocking()
|
||||||
else newMetaInstance()
|
} .map {
|
||||||
}
|
if(it != null) it.raise(metaClass)
|
||||||
|
else newMetaInstance()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Single.just(newMetaInstance())
|
Single.just(newMetaInstance())
|
||||||
}
|
}
|
||||||
@ -76,10 +78,12 @@ interface LewdSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
*/
|
*/
|
||||||
fun getOrLoadMetadata(mangaId: Long?, inputProducer: () -> Single<I>): Single<M> {
|
fun getOrLoadMetadata(mangaId: Long?, inputProducer: () -> Single<I>): Single<M> {
|
||||||
val metaObservable = if(mangaId != null) {
|
val metaObservable = if(mangaId != null) {
|
||||||
db.getFlatMetadataForManga(mangaId).asRxSingle()
|
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
||||||
.map {
|
Single.fromCallable {
|
||||||
it?.raise(metaClass)
|
db.getFlatMetadataForManga(mangaId).executeAsBlocking()
|
||||||
}
|
}.map {
|
||||||
|
it?.raise(metaClass)
|
||||||
|
}
|
||||||
} else Single.just(null)
|
} else Single.just(null)
|
||||||
|
|
||||||
return metaObservable.flatMap { existingMeta ->
|
return metaObservable.flatMap { existingMeta ->
|
||||||
|
@ -3,6 +3,7 @@ package exh.favorites
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
|
import com.elvishew.xlog.XLog
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
@ -21,7 +22,6 @@ import exh.util.trans
|
|||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import rx.subjects.BehaviorSubject
|
import rx.subjects.BehaviorSubject
|
||||||
import timber.log.Timber
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
@ -47,6 +47,8 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
private var wifiLock: WifiManager.WifiLock? = null
|
private var wifiLock: WifiManager.WifiLock? = null
|
||||||
private var wakeLock: PowerManager.WakeLock? = null
|
private var wakeLock: PowerManager.WakeLock? = null
|
||||||
|
|
||||||
|
private val logger = XLog.tag("EHFavSync").build()
|
||||||
|
|
||||||
val status = BehaviorSubject.create<FavoritesSyncStatus>(FavoritesSyncStatus.Idle())
|
val status = BehaviorSubject.create<FavoritesSyncStatus>(FavoritesSyncStatus.Idle())
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@ -73,7 +75,7 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
exh.fetchFavorites()
|
exh.fetchFavorites()
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
status.onNext(FavoritesSyncStatus.Error("Failed to fetch favorites from remote server!"))
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,11 +127,11 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
}
|
}
|
||||||
} catch(e: IgnoredException) {
|
} catch(e: IgnoredException) {
|
||||||
//Do not display error as this error has already been reported
|
//Do not display error as this error has already been reported
|
||||||
Timber.w(e, "Ignoring exception!")
|
logger.w( "Ignoring exception!", e)
|
||||||
return
|
return
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
status.onNext(FavoritesSyncStatus.Error("Unknown error: ${e.message}"))
|
status.onNext(FavoritesSyncStatus.Error("Unknown error: ${e.message}"))
|
||||||
Timber.e(e, "Sync error!")
|
logger.e( "Sync error!", e)
|
||||||
return
|
return
|
||||||
} finally {
|
} finally {
|
||||||
//Release wake + wifi locks
|
//Release wake + wifi locks
|
||||||
@ -228,7 +230,7 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} 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 Idle : FavoritesSyncStatus("Waiting for sync to start")
|
||||||
class Initializing : FavoritesSyncStatus("Initializing sync")
|
class Initializing : FavoritesSyncStatus("Initializing sync")
|
||||||
class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(if(isThrottle)
|
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
|
else
|
||||||
message)
|
message)
|
||||||
class CompleteWithErrors(messages: List<String>) : FavoritesSyncStatus(messages.joinToString("\n"))
|
class CompleteWithErrors(messages: List<String>) : FavoritesSyncStatus(messages.joinToString("\n"))
|
||||||
|
@ -24,14 +24,15 @@ data class FlatMetadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun DatabaseHelper.getFlatMetadataForManga(mangaId: Long): PreparedOperation<FlatMetadata?> {
|
fun DatabaseHelper.getFlatMetadataForManga(mangaId: Long): PreparedOperation<FlatMetadata?> {
|
||||||
fun getSingle() = getSearchMetadataForManga(mangaId).asRxSingle().flatMap { meta ->
|
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
||||||
if(meta == null) Single.just(null)
|
fun getSingle() = Single.fromCallable {
|
||||||
else Single.zip(
|
val meta = getSearchMetadataForManga(mangaId).executeAsBlocking()
|
||||||
getSearchTagsForManga(mangaId).asRxSingle(),
|
if(meta != null) {
|
||||||
getSearchTitlesForManga(mangaId).asRxSingle()
|
val tags = getSearchTagsForManga(mangaId).executeAsBlocking()
|
||||||
) { tags, titles ->
|
val titles = getSearchTitlesForManga(mangaId).executeAsBlocking()
|
||||||
|
|
||||||
FlatMetadata(meta, tags, titles)
|
FlatMetadata(meta, tags, titles)
|
||||||
}
|
} else null
|
||||||
}
|
}
|
||||||
|
|
||||||
return object : PreparedOperation<FlatMetadata?> {
|
return object : PreparedOperation<FlatMetadata?> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user