Explain the three MutableSharedFlow constructor parameters: replay, extraBufferCapacity, and onBufferOverflow. How do they interact?
answer
- buffer = replay + extraBufferCapacity
- replay = what NEW subscribers re-get
- extra = head-room so emit doesn't suspend
- SUSPEND (default) / DROP_OLDEST / DROP_LATEST
- DROP_* => tryEmit always true, emit never suspends
basics
~10 sreplay sets how many recent values new collectors get. extraBufferCapacity adds room for emitters when collectors are slow. onBufferOverflow decides what happens when both are full: suspend, drop oldest, or drop newest.
solid answer
~40 sMutableSharedFlow(replay, extraBufferCapacity, onBufferOverflow) controls a shared buffer of size replay + extraBufferCapacity. replay is how many most-recent values are cached and re-emitted to every new subscriber (replay cache). extraBufferCapacity is additional slots beyond the replay cache that let fast emitters proceed without suspending while slow collectors catch up. onBufferOverflow (BufferOverflow enum) defines behaviour when the whole buffer is full and a slow subscriber still hasn't consumed: SUSPEND (default — emit suspends, applying back-pressure), DROP_OLDEST (evict oldest buffered value, emit never suspends), or DROP_LATEST (discard the value being emitted). With DROP_OLDEST/DROP_LATEST, tryEmit always succeeds. If replay=0 and extraBufferCapacity=0, the only valid non-suspending behaviour combinations are limited and emit suspends until all subscribers are ready (rendezvous-like).
go deeper
Knows replay re-delivers recent values to new collectors at a high level.
Correctly separates replay (cache for new subs) from extraBufferCapacity (emitter head-room) and names the three BufferOverflow modes.
Explains the buffer = replay+extra interaction, the rendezvous behaviour at zero capacity, and picks a policy from latency/loss trade-offs.
Designs bus capacity/overflow policy against subscriber-speed distribution and memory budget, and reasons about lossy vs back-pressured event delivery system-wide.
## The factory ```kotlin public fun <T> MutableSharedFlow( replay: Int = 0, extraBufferCapacity: Int = 0, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND ): MutableSharedFlow<T> ``` Total buffer size = **`replay + extraBufferCapacity`**. ## replay The number of most recent values kept in the **replay cache** and re-emitted, in order, to **every new collector** the moment it subscribes. `replay = 0` means new subscribers see nothing from the past — only values emitted after they subscribe. You can clear it with `resetReplayCache()`. ## extraBufferCapacity Slots **beyond** the replay cache. They give emitters head-room: a fast `emit` can place values here and return without suspending while a slow collector is still draining. They are **not** replayed to new subscribers. ## onBufferOverflow (BufferOverflow) Applies only when the **entire** buffer (replay + extra) is full **and** at least one subscriber is still behind: - **SUSPEND** (default): `emit` suspends until space frees up — true back-pressure. `tryEmit` returns `false`. - **DROP_OLDEST**: evicts the oldest value in the buffer to make room; `emit` never suspends and `tryEmit` always returns `true`. - **DROP_LATEST**: discards the value currently being emitted, keeping existing buffered values; `emit` never suspends, `tryEmit` returns `true`. ## Interactions to remember - With `replay=0, extraBufferCapacity=0, SUSPEND`: `emit` behaves like a rendezvous — it suspends until **all** current subscribers receive the value, and `tryEmit` returns `false` if there is any slow subscriber. - DROP_OLDEST / DROP_LATEST are only meaningful when there is a buffer to overflow; combined with capacity they make emission lossy but non-blocking. - A subscriber that is slower than the buffer can drain causes the configured overflow policy to kick in — this is the central tuning decision. ```kotlin // Lossy, non-suspending event bus that keeps the latest 64 val bus = MutableSharedFlow<Event>( replay = 0, extraBufferCapacity = 64, onBufferOverflow = BufferOverflow.DROP_OLDEST ) ```
- With replay=0 and extraBufferCapacity=0, what does emit do under a slow collector?It suspends until every current subscriber has received the value (rendezvous-like), and tryEmit returns false.
- Does extraBufferCapacity get replayed to new subscribers?No. Only the replay cache (size = replay) is replayed; extra buffer slots are emitter head-room only.
saying these in an interview costs you the question
- Saying extraBufferCapacity values are replayed to new subscribers
- Claiming DROP_OLDEST can cause emit to suspend
- Thinking onBufferOverflow matters even when no subscriber is slow
- Believing total buffer is max(replay, extraBufferCapacity) rather than the sum