are there example impls of recommended patterns fo...
# coroutines
h
are there example impls of recommended patterns for achieving something similar to this intra-process EventBus but with coroutines (or project reactor)? #events https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/eventbus/EventBus.html
spring boot examples would be even better 🙂
a
You saw the giant, "Avoid EventBus" header in the docs there, right? 🙂
h
That's exactly why I posed this question 🙂
a
You won't find a lot of direct translations of the EventBus pattern because it's the pattern, not the implementation, that creates the problems with EventBus.
A single hot stream of multiplexed heterogeneous events creates the problems in the bulleted list there
the closest thing you might find for info around taming this sort of thing might be in MQTT application protocol design
but most of the effective MQTT design patterns out there more or less emulate the sorts of things you would do with observable state (using retained messages) and explicitly designing event protocols to be stateless
but that's more of a curiosity; the sort of thing that answers the, "but what about...?" questions around other popular pub/sub systems. They've all had to wrestle with these things
I'd start with some of the core coroutines patterns from the ground up and what problems they solve; peel off the use cases for EventBus one by one, replacing each with more suitable patterns
h
What we're currently looking for isn't necessarily multiplexed heterogeneous events from a single stream, but at least the ability to have multiple consumers of the same event. Each event type could be it's own stream or topic. Seems like with coroutine channels and reactor flux, it's limited to consume once by one subscriber
Which seems to be the diff between the Pub sub and observer patterns? Looking for the former
a
Multiple consumers for single events is the hardest case to design for. If you can get out of this case you will often be better off.
Cases you must handle if you choose this path: • What if the "right" observer isn't observing when the event intended for it is fired? • What if an observer misses events from the beginning of a series of related events? • What if an observer misses events from the end of a series of related events? • What if an observer misses events from the middle of a series of related events? All of these imply that in a multi-consumer event stream, either you must be able to guarantee that all consumers are present before the stream begins sending any events and will be present all the way until the event stream ends, or the event stream cannot form a stateful protocol. (i.e. you can't define EVENT_BEGIN, EVENT_MIDDLE, EVENT_END type events to send to it with rules about the order they can appear in)
You can also define observable state to solve some of these problems; the multi-consumer observable endpoint reduces any incoming events into one complete record of state, and observers observe that state instead of the event stream that produced it. (e.g. StateFlow, .stateIn(...))
It's always safe for multiple consumers to observe state and come and go as they please, since state is idempotent. State is. It only tells you the current state of the system, nothing about how it got there.
It's fine for multiple consumers to observe the current temperature reported by a sensor and to come and go as they please, since that value is just state.
h
Observing current state is easy (it's persisted to a DB in this case), the use case here tho is informing the subscribers that something has changed, in a decoupled way, and therefore the state needs to be re fetched to update something. It's the change event that we're solving for broadcasting to trigger that observation when it's needed
a
sounds like a standard cold source of state to me. Room over on Android does this for sqlite databases; you get a Flow<Foo> that gives you the latest value whenever it changes. It sets up a database change observer when a subscriber is active, and internally deduplicates those if multiple subscribers are present. It sends the current value immediately whenever you start observing.
h
interesting, Room seems to depend on rxjava
I'm gonna try doing something similar to this based on your suggestion to use SharedFlow: https://medium.com/tech-takeaways/how-to-implement-the-event-bus-pattern-with-kotlin-sharedflow-in-your-android-app-768529828607
closest I've found so far, and the first snippet is in the kotlin docs as well
a
Room has peer integrations with Rx and Flow
I can't stress enough that using new tools to implement the EventBus pattern is just as troublesome as EventBus itself
Using coroutines to implement that pattern is not going to make those problems go away