确保 RxWorker 永远不会失败

huangapple go评论62阅读模式
英文:

Ensure an RxWorker never fails

问题

Here is the translated portion of your text:

"我正在实现我的第一个WorkManager,用于与服务器进行每日同步,可能会返回HTTP错误,因此使createWork()流失败并调用onError(),所以在流的订阅中会"抛出" Result.failure()

我想确保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())
        }
    }
}"

If you have any specific questions or need further assistance with your code, please feel free to ask.

英文:

I'm implementing my first WorkManager for daily sync with the server which could return an HTTP error hence make the createWork() flow to fail and to call onError() so a Result.failure() is "thrown" in the flow's subscription.

I would like to make sure Result.failure() is never called and always call Result.retry().

Here is my 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 = &quot;com.blabla.blah.DAILY_SYNC_WORKER&quot;
    }

    override fun createWork(): Single&lt;Result&gt; {
        Timber.e(&quot;Worker - Executing ${System.currentTimeMillis() - prefsManager.lastMillis}&quot;)
        prefsManager.lastMillis = System.currentTimeMillis()

        return dbManager.alarmDAO.getNewAlarms(prefsManager.lastSyncedAlarm)
            .flatMap { alarms -&gt; 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&lt;Alarm&gt;): Single&lt;Result&gt; {
        val syncRequestModel = SyncRequestModel(alarms)

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

I tried calling Result.retry() in many different onError() of the flow but it seems that Result.failure() is being called in the onError() of the subscription which I can't override.

So how can I make sure my worker never fails?

答案1

得分: 1

In syncWithServer() function, you only check result in flatMap part. However, there might be cases that error might happen before reaching flatMap part which means Result.retry() might never be returned. Also, you do not need to specify specific thread as workers run on background thread by default. Here is your worker with changes I mentioned above:

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())
        }
    }
}
英文:

In syncWithServer() function, you only check result in flatMap part. However, there might be cases that error might happen before reaching flatMap part which means Result.retry() might never be returned. Also, you do not need to specify specific thread as workers run on background thread by default. Here is your worker with changes I mentioned above:

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 = &quot;com.blabla.blah.DAILY_SYNC_WORKER&quot;
    }

    override fun createWork(): Single&lt;Result&gt; {
        Timber.e(&quot;Worker - Executing ${System.currentTimeMillis() - prefsManager.lastMillis}&quot;)
        prefsManager.lastMillis = System.currentTimeMillis()

        return dbManager.alarmDAO.getNewAlarms(prefsManager.lastSyncedAlarm)
            .flatMap { alarms -&gt; 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&lt;Alarm&gt;): Single&lt;Result&gt; {
        val syncRequestModel = SyncRequestModel(alarms)

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

huangapple
  • 本文由 发表于 2020年1月3日 23:05:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定