I have a long running job that I would like to pub...
# coroutines
a
I have a long running job that I would like to publish progress for. Currently the API looks like this:
Copy code
suspend fun performHeavyWork()
Would it be advisable to use an actor for this case? The callee should be able to receive a progress value between 0-1 (or 0-100).
o
I think you want a
producer
here -- the function can return
ReceiveChannel<Int>
, which the callee can use to get progress values. Of course, this won't work if you want to return something else, in which case I would make a sealed class, something like
Event
with
Progress
and
Result
subclasses. Then you can send progress events until you are done, and send a result event with the final data.
g
I just use callback for progress, it’s easier to use (doesn’t pollute API, progress is optional) and less overhead
a
I can’t return anything since the function doesn’t return until it’s completed
g
What do you mean?
My suggestion is to add progress callback to function
Copy code
suspend fun doSomething(progress: ((Float) -> Unit)? = null): SomeResult
Progress lambda also can be suspend
a
I was responding to Kenzie’s comment. Progress callback works too but is semantically the same as a callback but is less flexible I would say
I would then have to manage context switching myself for example
b
You could also make that progress callback suspending so it could immediately do
withContext
and then
launch
invocations of your progress callback so it doesn’t block your
doSomething
from moving forward while progress notification is consumed
o
I think you misunderstood how producer works
it spawns a separate coroutine to do the work, and returns immediately
a
I could return a channel of course but then I loose the ability to cancel the job and suspend the caller until done
o
`producer`:
The running coroutine is cancelled when its receive channel is cancelled.
additionally, calling
receiveOrNull
suspends until done if no more progress is being made