-
Notifications
You must be signed in to change notification settings - Fork 112
Description
since worker is built on runningSideEffect, the easier way to reproduce this is:
runningSideEffect("test") {
try {
} finally {
error()
}
}
If this is rendered and not rendered within the same thread frame (e.g. using the Main.Immediate dispatcher and cycling back and forth), error() will never get called.
At the very least this needs to be updated in the documentation.
This is because the Job's for side effects are started using CoroutineStart.LAZY so that we don't end up sending anything to the actionSink until after the render() method is complete and the RenderContext frozen (then we call start() on all the side effect jobs - see here.
baseRenderContext.unfreeze()
val rendering = interceptor.intercept(workflow, this)
.render(props, state, context)
baseRenderContext.freeze()
// Tear down workflows and workers that are obsolete.
subtreeManager.commitRenderedChildren()
// Side effect jobs are launched lazily, since they can send actions to the sink, and can only
// be started after context is frozen.
sideEffects.forEachStaging { it.job.start() }
sideEffects.commitStaging { it.job.cancel() }
What would be better if we provided a hook to the side effect's Job's invokeOnCompletion which will be invoked even if cancelled before the coroutine gets dispatched. E.g. see this test:
fun main() = runBlocking {
val job = launch(start = CoroutineStart.LAZY) {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
} finally {
println("I'm still run in the finally block.")
}
}
job.invokeOnCompletion { cause ->
println("I'm complete! $cause")
}
job.start()
//yield()
job.cancel()
println("done test.")
}
Which prints "I'm complete" but not what is in the finally block (without the yield()).
I propose this could be called.
RenderContext.onNoLongerRendered(). It has to be outside of runningSideEffect's lambda because that won't ever get invoked. We want to attach this right on the Job we create for the side effect.