diff --git a/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibEvents.kt b/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibEvents.kt index 2178e876..194e472e 100644 --- a/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibEvents.kt +++ b/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibEvents.kt @@ -20,20 +20,52 @@ import io.reactivex.Observable import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.rx2.asObservable public object RibEvents { + private var extraBufferCapacity: Int = Channel.UNLIMITED - private val mutableRouterEvents = - MutableSharedFlow(0, Channel.UNLIMITED, BufferOverflow.DROP_OLDEST) - private val mutableRibDurationEvents = - MutableSharedFlow(0, Channel.UNLIMITED, BufferOverflow.DROP_OLDEST) + /** + * Sets the extra buffer capacity for [routerEventsFlow] and [ribActionEventsFlow]. + * + * This function must be called on the main thread, and before any usage of: + * 1. [routerEventsFlow] + * 2. [routerEvents] + * 3. [ribActionEventsFlow] + * 4. [ribActionEvents] + */ + @JvmStatic + public fun setExtraBufferCapacity(capacity: Int) { + extraBufferCapacity = capacity + } + + private val mutableRouterEvents by lazy { + MutableSharedFlow(0, extraBufferCapacity, BufferOverflow.DROP_OLDEST) + } + + private val mutableRibDurationEvents by lazy { + MutableSharedFlow(0, extraBufferCapacity, BufferOverflow.DROP_OLDEST) + } + + @JvmStatic + public val routerEventsFlow: SharedFlow by lazy { + mutableRouterEvents.asSharedFlow() + } @JvmStatic - public val routerEvents: Observable = mutableRouterEvents.asObservable() + public val routerEvents: Observable by lazy { mutableRouterEvents.asObservable() } @JvmStatic - public val ribActionEvents: Observable = mutableRibDurationEvents.asObservable() + public val ribActionEventsFlow: SharedFlow by lazy { + mutableRibDurationEvents.asSharedFlow() + } + + @JvmStatic + public val ribActionEvents: Observable by lazy { + mutableRibDurationEvents.asObservable() + } /** Indicates if [ribActionEvents] will be emitting. */ public var areRibActionEmissionsAllowed: Boolean = false diff --git a/android/libraries/rib-base/src/test/kotlin/com/uber/rib/core/RibEventsTest.kt b/android/libraries/rib-base/src/test/kotlin/com/uber/rib/core/RibEventsTest.kt new file mode 100644 index 00000000..06f258bd --- /dev/null +++ b/android/libraries/rib-base/src/test/kotlin/com/uber/rib/core/RibEventsTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.rib.core + +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Ignore +import org.junit.Test +import org.mockito.kotlin.mock + +@OptIn(ExperimentalCoroutinesApi::class) +@Ignore( + """ + Test only passes when running in isolation: RibEvents flows might've been accessed + when running full suite. + """, +) +class RibEventsTest { + private val extraBufferCapacity = 16 + + @Before + fun setUp() { + RibEvents.setExtraBufferCapacity(extraBufferCapacity) + } + + @After + fun tearDown() { + RibEvents.setExtraBufferCapacity(Channel.UNLIMITED) + } + + @Test + fun setExtraBufferCapacityTest() = runTest { + val results = mutableListOf() + backgroundScope.launch { RibEvents.routerEventsFlow.collect(results::add) } + runCurrent() + repeat(32) { RibEvents.emitRouterEvent(RibEventType.ATTACHED, mock(), mock()) } + runCurrent() + assertThat(results.size).isEqualTo(16) + } +}