TL;DR Looking for recommendations on robust offline support using rx-kotlin.
I've followed a nice guide on offline-support in Android apps. It works like this:
The code is:
Observable.mergeDelayError(
loadRemoteData()
.doOnNext { writeDataToLocalDatabase(it) }
.subscribeOn(Schedulers.io()),
loadDataFromLocalDatabase()
.subscribeOn(Schedulers.io())
)
Unfortunately, this approach relies on the database code always working. If the database operations for some reason fail, everything fails, even when the data is loaded successfully from the remote server.
Is there a way I can achieve the following using rx-kotlin/rx-java?:
I'd like to avoid loading the data from the Internet twice. I'm using room + retrofit, if that matters.
EDIT: Thanks to @MinseongPark, I ended up with the code below. The mergeDelayError reports an error only if both the remote and the local source fails, and if the writeDataToLocalDatabase method fails (throws an Exception), then that does not keep the remote data from being reported to the UI. The information about errors in writeDataToLocalDatabase is saved by reporting it remotely. Now, the code is robust to one of the two sources failing, and to writing new entries to the database failing.
return Observable.mergeDelayError(
loadRemoteData().doOnNext {
try {
writeDataToLocalDatabase(it)
} catch (error: Throwable) {
Timber.d(error)
Crashlytics.logException(error)
}
},
loadDataFromLocalDatabase()
)
.subscribeOn(Schedulers.io())
Try this.
Observable.mergeDelayError(
loadRemoteData()
.doOnNext { runCatching { writeDataToLocalDatabase(it) } }
.subscribeOn(Schedulers.io()),
loadDataFromLocalDatabase()
.onErrorResumeNext(Observable.empty())
.subscribeOn(Schedulers.io())
)