https://kotlinlang.org logo
#uniflow
Title
# uniflow
e

Erik

01/23/2020, 10:35 AM
Instead of `offer`ing to the actor channel, uniflow could also
send
to it.
A few differences: -
offer
is synchronous, non suspending -
offer
returns a boolean, i.e. if the channel accepted the offered item or not (buffer full) -
send
is a
suspend fun
-
send
either returns quickly if item accepted by channel (buffer not full), or suspends the caller if not accepted, until the item can be accepted
The latter might be useful to remove the need for a buffered channel at all.
However
Suspending the coroutine that is `send`ing to the channel might lead to unexpected behaviour, because if the channel processes items sent to too slow, or items are sent to it too quickly, then a lot of coroutines might suspend and queue up to send items to the actor channel
A combination of both might be an option: Give the actor channel a buffer and use
send
. Then up to the buffer capacity of state actions can be buffered, any additional
send
events will suspend
This might be prefereable, because:
Hypothetically, if the buffer is almost full (1 space left), then if I dispatch a
setState { LoadingState }
, that would work just fine. Then I load my data and after that succeeds, then I'd
setState { DataState }
, but the buffer now is full! So that state would never be observed by my UI if
offer
is used. Eventually, my UI would stay in the
Loading
state, possibly forever.
This is not so nice
That would be one reason for using
send
instead of
offer
Any thoughts, @arnaud.giuliani and @Marcin Chrapowicz?
As a uniflow user I'd expect that uniflow processes all state actions that I dispatch
If my state actions are so slow that the channel's buffer fills up and a lot new state actions queue up, suspending many coroutines, then that's my problem as a user. That's nothing uniflow can do anything about.
m

Marcin Chrapowicz

01/23/2020, 10:48 AM
That is true, right now we are ignoring this last state ( We are sending logs 😕 ). We should consider to change that 👍
e

Erik

01/23/2020, 10:49 AM
m

Marcin Chrapowicz

01/23/2020, 10:56 AM
Sure 👍
👍 1
a

arnaud.giuliani

01/23/2020, 11:03 AM
buffering offer us a way to keep events in order
one side effect can to have multiple actions at a time and have them in a random way
e

Erik

01/23/2020, 11:24 AM
An
actor
is created on
AndroidDataFlow.coroutineScope
, so there is one actor only, operating in the same scope. From
SendChannel.send
KDoc:
All elements that are sent over the channel are delivered in first-in first-out order.
That does mean parallel user flows might happen somewhat simultaneously, but the individual flows themselves happen in order. Can you come up with an example where that would be problematic? E.g. the user presses a button once, but before all subsequent state actions are handled, they press it again a number of times? All subsequent
actor.send(action)
calls would suspend (if buffer full), but they'd suspend in order. So how could suspended
send(action)
calls become out of order? I think using
offer(action)
achieves exactly the same concurrent and in-order behaviour, with the difference that if the buffer is full then nothing is offered at all.
a

arnaud.giuliani

01/24/2020, 1:26 PM
he difference that if the buffer is full then nothing is offered at all.
insteresting 👍
e

Erik

01/24/2020, 1:51 PM
And if uniflow sticks to
offer
for good reasons, then at least let the user know that something went wrong (other than just logging an error), e.g. throw an exception, return
null
or
false
, or a callback
a

arnaud.giuliani

01/24/2020, 3:50 PM
yes, sure it's a good thing to give feedback
2 Views