The name of APPEND_OR_REPLACE is misleading, by reading this you will think that this Worker will REPLACE the previous worker in case of failure, or APPEND if it is RUNNING, which is wrong!
APPEND_OR_REPLACE means APPEND this worker to the running chain OR REPLACE the chain with a new one if the previous failed (create a new chain and start over, it is like a hard reset)
pseudo code
if (getChainWithUniqueTag(TAG).status == CANCELLED || FAILED) {
createNewChine()
}
addRequestToChainWithTag(TAG,request)
Now It should make more sense, it is about the state of current chain and not the Work
To confirm this more, try to start a worker1 with a unique name, and then fail it (by calling Result.failure) and then create another worker2 with APPEND with the same unique name, worker2 will fail directly before starting because it belongs to a failing chain.
If you try the same scenario but with APPEND_OR_REPLACE, worker2 will start a new chain and continue working normally.
Consider this example :
val request1 = OneTimeWorkRequestBuilder<SleepWorker>()
.setInputData(workDataOf(KEY_BREAK_AT to 5))
.build()
val request2 = OneTimeWorkRequestBuilder<SleepWorker>()
.build()
workManager.enqueueUniqueWork(
TAG,
ExistingWorkPolicy.APPEND_OR_REPLACE,
request1
)
// Infinite loop
while (workManager.getWorkInfoById(request1.id).get().state == WorkInfo.State.RUNNING){}
workManager.enqueueUniqueWork(
TAG,
ExistingWorkPolicy.APPEND_OR_REPLACE,
request2
)
SleepWorker
class SleepWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
val breakAt = inputData.getInt(KEY_BREAK_AT,-1)
repeat(10) {
if(it == breakAt) return Result.failure()
println("$it")
delay(1000L)
}
return Result.success()
}
}
Now in this case, request1 will fail, and then we start request2 and it will starts normally, because the FLAG is APPEND_OR_REPLACE,
If the flag is APPEND then request2 will fail.
PS: try to move the second enqueueUniqueWork for request2 before the infinite while loop, request2 will fail too. makes sense no ?
because when we called enqueueUniqueWork the chain was good at that time, and for that the job has been added to that chain successfully.