Does arrow-kt have a fire and forget concept ? I w...
# arrow
s
Does arrow-kt have a fire and forget concept ? I want to offload my computation (can be heavy IO ops) in the background. I have aware of
CoroutineScope.actor
. But was wondering if I can get something functional.
j
Up until recently, this was possible through Fiber: https://arrow-kt.io/docs/0.11/effects/fiber/ Not sure what the replacement of Fiber. 😵 Can't seem to find anything similar in the current version docs.
s
Fire and forget means you want to launch something on a new
CoroutineScope
and then forget about it.
Fiber
exposed several ways of launching a task in parallel, which are all covered already by
Deferred
and
CoroutineScope
. I didn't cover so much of this in the docs, because that would mean we'd basically be rewriting docs that belong into KotlinX Coroutines.
What is your use-case @Satyam Agarwal? Maybe we can figure out a nice solution together, and share it as an example on the Arrow website to cover this pattern 🙂
If people want to work on docs, or examples for the website that's great. Or anything else, I'm always up to help with whatever needed 🙂
s
Awesome. So for example, I have one api which determines if the response was success, then the user should see message A immediately, but as soon as user is done reading the message A and goes to the next screen, another api call need to be made. So instead of making this call on the second screen, I can fire and forget about it in the beginning when calling api that returns message A. The state for screen B can be updated in the background, and perhaps by the time user comes to it.
Another example : I have an interceptor that log request and responses, for all the backend api called, Then I don’t want to wait for the logs to get written, and want to return the control immediately. So a
Coroutine.actor
gives this kind of support. You launch operations to this actor, and then you can read from the channel of this actor to write logs in the order they came.
Logging in the background may not be a good example, but if you don’t care about the timestamp, then its nice to offload it in the backgroud.
But atleast the order is preserved
s
All right, I have a couple of questions and then I'm gonna try to whip some snippets up. In the first example, what do you do with the result of
B
? To fire and forget you could use a locally created
CoroutineScope
or
GlobalScope
Copy code
CoroutineScope(Dispatchers.Default).launch {
  f()
}
but if you're on Android or any other cancellable framework I think it would be better to use
viewModelScope
(of
B
) for example or a
CoroutineScope
that lives on an
App
level rather than a screen level.
For example 2, On what
CoroutineScope
would you calling the
actor
? I think I'd just use a
Channel
to replace the
actor
and consume it as a
Flow
.
j
The unification of Arrow Fx and kotlinx Coroutines blows my mind! Well done! (Docs on why Fiber is not longer needed or a duplication of kotlinx Coroutines docs is not needed (for me, I know enough now).)
s
Hey @simon.vergauwen This all is a backend system.
what do you do with the result of B ?
The result gets evaluated and a state in the database is updated. So once backend gets a request to show new state, this perhaps updated state may be returned.
On what CoroutineScope would you calling the actor?
I was thinking :
CoroutineScope(SupervisorJob() + IO).actor
I think I’d just use a Channel to replace the actor and consume it as a Flow.
You mean some thing like this : https://kotlinlang.org/docs/flow.html#buffering
s
This all is a backend system
Oh, then things are a bit simpler 🙂 What back-end are you using?
CoroutineScope(SupervisorJob() + IO).actor
is not a great option, since this is not tied to any lifecycle. You'd probably want to hook this into the lifecycle of your back-end, and preferably suspending even on
close
so that the back-end closes gracefully.
s
intersting. I am using ktor. So I was thinking to do something like :
Copy code
CoroutineScope(SupervisorJob() + IO).launch { 
    f()
}
like you suggested. But then this
CoroutineScope
is not connected to ktor, no. How do you suggest I achieve it ?
I was thinking to make
val appScope = CoroutineScope(SupervisorJob() + IO)
and use
appScope
everywhere. Since it is not tied to a parent scope, I fear it can get garbage collected ? Thinking to make singleton like :
Copy code
object BackgroundScope : CoroutineScope {
    override val coroutineContext: CoroutineContext = SupervisorJob() + IO
}
s
Ktor
does have a (parent)
Application
scope available though. https://api.ktor.io/1.5.4/io.ktor.application/-application/
So you want to tie all that background stuff to that
CoroutineScope
and then you should be good 🙂
I'm not so familiar with
SharedFlow
and afaik you don't need it since Ktor has full support for
suspend
everywhere. In such cases (just like with
IO
) I prefer data typs that offer me proper strategies such as bounded, slide, drop etc.
s
Hmm. makes sense. thanks 🙂