确保 RxWorker 永不失败

Ensure an RxWorker never fails

我正在实施我的第一个 WorkManager 与服务器的日常同步,这可能 return 一个 HTTP 错误因此使 createWork() 流程失败并调用 onError() 所以 Result.failure() 在流程的订阅中是 "thrown"。

我想确保永远不会调用 Result.failure() 并始终调用 Result.retry()

这是我的 RxWorker

class DailySyncWorker (appContext: Context, workerParams: WorkerParameters): RxWorker(appContext, workerParams) {

    private val disposable: CompositeDisposable = CompositeDisposable()
    private val httpManager = AppFactory.httpManager()
    private val dbManager = AppFactory.dbManager()
    private val prefsManager = AppFactory.sharedManager(appContext)

    companion object {
        const val WORKER_NAME = "com.blabla.blah.DAILY_SYNC_WORKER"
    }

    override fun createWork(): Single<Result> {
        Timber.e("Worker - Executing ${System.currentTimeMillis() - prefsManager.lastMillis}")
        prefsManager.lastMillis = System.currentTimeMillis()

        return dbManager.alarmDAO.getNewAlarms(prefsManager.lastSyncedAlarm)
            .flatMap { alarms -> syncWithServer(alarms)
                .doOnSuccess {
                    if(alarms.size != 0)
                        prefsManager.lastSyncedAlarm = alarms[0].date // The query is in descending order, the first record is the last recorded alarm
                }
            }
    }

    private fun syncWithServer(alarms: MutableList<Alarm>): Single<Result> {
        val syncRequestModel = SyncRequestModel(alarms)

        return if(alarms.size != 0)
            httpManager.service().create(SyncService::class.java).sync(syncRequestModel)
                    .observeOn(Schedulers.io())
                    .flatMap { result ->
                        if(result == "OK") { // TODO - the service has not been created yet
                            Timber.e("Worker - success")
                            Single.just(Result.success())
                        } else {
                            Timber.e("Worker - failure")
                            Single.just(Result.retry())
                        }
                    }
        else {
            Timber.e("Worker - no sync is necessary")
            Single.just(Result.success())
        }
    }
}

我尝试在许多不同的 onError() 流程中调用 Result.retry(),但似乎 Result.failure() 在订阅的 onError() 中被调用,我可以' t覆盖。

那么我怎样才能确保我的工人永远不会失败?

syncWithServer()函数中,你只检查flatMap部分的结果。但是,在到达 flatMap 部分之前可能会发生错误,这意味着 Result.retry() 可能永远不会返回。此外,默认情况下,您不需要在后台线程上将特定线程指定为 workers 运行。这是您的工作人员,其中包含我上面提到的更改:

class DailySyncWorker (appContext: Context, workerParams: WorkerParameters): RxWorker(appContext, workerParams) {

    private val disposable: CompositeDisposable = CompositeDisposable()
    private val httpManager = AppFactory.httpManager()
    private val dbManager = AppFactory.dbManager()
    private val prefsManager = AppFactory.sharedManager(appContext)

    companion object {
        const val WORKER_NAME = "com.blabla.blah.DAILY_SYNC_WORKER"
    }

    override fun createWork(): Single<Result> {
        Timber.e("Worker - Executing ${System.currentTimeMillis() - prefsManager.lastMillis}")
        prefsManager.lastMillis = System.currentTimeMillis()

        return dbManager.alarmDAO.getNewAlarms(prefsManager.lastSyncedAlarm)
            .flatMap { alarms -> syncWithServer(alarms)
                .doOnSuccess {
                    if(alarms.size != 0)
                        prefsManager.lastSyncedAlarm = alarms[0].date // The query is in descending order, the first record is the last recorded alarm
                }
            }
            .onErrorReturnItem(Result.retry()) // Here is error handling
    }

    private fun syncWithServer(alarms: MutableList<Alarm>): Single<Result> {
        val syncRequestModel = SyncRequestModel(alarms)

        return if(alarms.size != 0)
            httpManager.service().create(SyncService::class.java).sync(syncRequestModel)
                    .flatMap { result ->
                        if(result == "OK") { // TODO - the service has not been created yet
                            Timber.e("Worker - success")
                            Single.just(Result.success())
                        } else {
                            Timber.e("Worker - failure")
                            Single.just(Result.retry())
                        }
                    }
        else {
            Timber.e("Worker - no sync is necessary")
            Single.just(Result.success())
        }
    }
}