second question: ```val backgroundTask = IO.fx { ...
# arrow
s
second question:
Copy code
val backgroundTask = IO.fx {
            effect { Timber.d("starting sleep...") }.bind()
            sleep(10.seconds).bind()
            effect { Timber.d("sleep ended...") }.bind()
            raiseError<Unit>(Throwable("Bang!!")).bind()
        }

        IO.fx {
            effect { _viewState.postValue(ViewState.Loading) }.bind()
            continueOn(Dispatchers.Default)
            backgroundTask.fork().bind()
            ViewState.Content(GithubService.model) // show static data
        }
            .handleError { ViewState.Error(it.errorMessage()) }
            .flatMap { IO.effect { _viewState.postValue(it) } }
            .unsafeRunScoped(viewModelScope) { }
if my
ViewModel
gets destroyed here, the
backgroundTask
continues executing (as expected). However after is done, the error is swallowed. Is that the expected behavior? 🤔
s
What do you expect to happen here? You’re forking an operation, or in other words you’re decoupling it’s lifecycle.
It’s like calling
async
without a
CoroutineScope
.
s
Some global error handler maybe?
I intended for it to be decoupled. And would be fine to succeed silently.... The silent error is a bit unexpected for me
s
Where would you expect it to bubble up?
s
When I do fire and forget for RxJava I use Completable and I usually handle the error locally with
onErrorComplete
Otherwise it goes to the RxJava global error handler and my app blows up...
s
You can also install
onError
handlers for
IO
, and they take
IO
actions instead of
() -> Unit
So you’d want a
fireAndForget
operation that happened in a fiber to blow up your app by default?
s
I'm not sure... Just pointing out where I come from and why this was a bit surprising
s
Yes, I understand. This doesn’t seem weird to me since if I decouple a process, I except it to be decoupled. If I want to wire two processes together, than well I need to do something else than just decouple a process.
👍 1
s
I guess it's one of those things where there is no perfect solution, just different trade offs
s
Yes, definitely
s
In the case of
forkConnected
, which is the equivalent of `CoroutineScope.async`` would you expect that the error is send to an
asyncErrorHandler
as well as stay inside the
Fiber
for when you
join
it? So the
error
would be guaranteed to show up once in the
asyncErrorHandler
on top of the
N
times you can
join
it?
loosing it is not perfect, but having it delivered
N
times ... not sure
maybe if it was delivered to ``asyncErrorHandler`` and you join, it should be wrapped so you know it was already handled....
but then again... maybe the current behavior is good enough
it's a simpler mental model..... if you do a
fork
and throw away the cancellation token it means you don't care about the result, and if the result is error or success the behavior is the same....