How flatMap works and its implications
masterThe flatMap operator is considered a "loopy" operator because it allows for two behaviors that break the standard synchronous transaction model:
- Multiple emissions: It can emit more than one event for a single incoming event.
- Graph cycles: It can create a loop where an observable depends on itself (directly or indirectly).
Because Airstream relies on a static topological rank to prevent glitches, and flatMap makes the graph structure dynamic (the dependency can change based on the emitted value), it cannot be part of the synchronous DAG. Consequently, every event from a flatMap is emitted in a new transaction.
To avoid complexity and potential issues, use combineWith if your logic does not strictly require the dynamic re-shaping of the stream provided by flatMap.
val intStream: EventStream[Int] = ???
val flatIntStream: EventStream[Int] = intStream.flatMap { ev =>
EventStream.fromSeq(List(ev + 1, ev + 2))
}