https://kotlinlang.org logo
Title
m

mcpiroman

11/29/2021, 5:59 PM
I need a simple way to send stateless notifications, currently I have:
val focusRequests = MutableSharedFlow<Unit>(onBufferOverflow = BufferOverflow.DROP_LATEST, extraBufferCapacity = 1)
focusRequests.tryEmit(Unit) // on frontend
focusRequests.collect { ... } // on backend
but I feel like this is an abuse of the SharedFlow. Is there more specific construct I should use in such cases?
d

Dominaezzz

11/29/2021, 6:03 PM
Why does it feel abusive?
Looks fine to me
m

mcpiroman

11/29/2021, 6:16 PM
Well, it uses a unnecessary buffer of 1, passes around unnecessary instance of Unit, on callside uses `tryEmit`even though it is bound to success, has quite complicated configuration in the constructor for such a simple and common usage. I'd expect more of a volatile boolean rather than a queue as an implementation - and I'm not talking about performance, I suspect there is not too much of an overhead, just the idea. If this is the preferred way I would like at least some constructor function or other wrapper built-in.
d

Dominaezzz

11/29/2021, 6:19 PM
Volatile Boolean?
m

mcpiroman

11/29/2021, 6:26 PM
Ok, that's a metaphor, maybe more of a java's `Object.notify`probably with some array of collectors. But currently the SharedFlowImpl has 9 fields. Seems quite wasteful for when I don't need any data, queuing, suspending etc.
d

Dominaezzz

11/29/2021, 7:23 PM
Maybe you want StateFlow?
m

mcpiroman

11/29/2021, 7:27 PM
StateFlow compares the value against the old one when updating, so `emit(Unit)`will do nothing. Even then, `StateFlow<Unit>`would read as 'state flow of no state'.
d

Dominaezzz

11/29/2021, 7:27 PM
Channel
?
👀 1
j

Joakim Forslund

11/29/2021, 7:44 PM
channelFlow? but I do agree, I don't really see anything wrong with given approach either, it just more fine tuned to handle back pressure
m

mcpiroman

11/29/2021, 7:49 PM
`ConflatedChannel`looks better but due to the nature of channels that would only work when I have 1 receiver
j

Joffrey

11/30/2021, 11:02 AM
passes around unnecessary instance of Unit
There is only one instance of the
Unit
object, so don't worry about this.
on callside uses 
tryEmit
even though it is bound to success
That sounds OK to me. The client doesn't know the backpressure strategy of that flow, so it makes sense IMO that the client expresses whether it is able to handle backpressure via suspension or whether it wants to just keep going (you could use emit if you're already in a suspending context, it won't suspend anyway). On the other side, the construction of the flow decides what to do for backpressure on its own.
it uses a unnecessary buffer of 1
Why do you consider it unnecessary? It allows slow subscribers to run multiple times in a row if one or more new notifications arrived while they were processing the previous one, it makes sense to have this buffer. You need somehow to store the "boolean state" you're referring to ("was there a notification since I last run?").
has quite complicated configuration in the constructor for such a simple and common usage.
It's true it could maybe be included in the coroutines library, but you could also define a simple wrapper around this yourself.