Android: Offline-first repository, 2 data source. Как обрабатывать ошибки?

Всем привет!

Подскажите, пожалуйста, как правильно осуществлять обработку ошибок при получении в репозитории данных из двух data source:

Есть репозиторий, который должен при вызове метода getOrders() запросить обновление данных от бэка и сразу же вернуть данные имеющиеся в локальной БД, чтобы пользователь не ждал подгрузки данных. Не понимаю как отправлять ошибки, которые могут произойти при обращении к Network Data Source на UI слой?

Понятно, что можно сделать какой-нибудь класс-обёртку типа Result<T> c наследниками Success/Error, но не понимаю какой тогда должен быть возвращаемый тип у getOrders. С Result<T> уже не вернешь StateFlow, а если пытаюсь делать Flow и эмиттить сначала ошибку, а потом данные из локального репозитория, то получаю Flow exception - Emission from another coroutine is detected. Или ошибки надо вообще на другом уровне обрабатывать?

Может кто поделиться примером как это надо обрабатывать и какие есть Best Practices на этот случай? Задача по сути проста: показать как можно быстрее пользователю данные из БД, загрузить свежие данные из сети, при этом в случае какой-либо ошибки показать юзеру Snackbar с сообщением об ошибке, не лишив его при этом, возможности работать с локальными данными.

@Singleton
class OrderRepositoryImpl @Inject constructor(
    private val localDataSource: LocalDataSource,
    private val networkDataSource: NetworkDataSource,
    userRepository: UserRepository,
    @DefaultDispatcher private val dispatcher: CoroutineDispatcher,
    @ApplicationScope private val scope: CoroutineScope
) : OrderRepository {

    override fun getOrders(forceUpdate: Boolean = false): StateFlow<List<Order>> {
        val user = userStateFlow.value ?: throw IllegalStateException("Undefined user")
        if (forceUpdate) {
            scope.launch {
                try {
                    val remoteOrders = networkDataSource.loadOrders()
                    localDataSource.updateOrders(remoteOrders)
                } catch (e: Exception) {
                    //TODO:Прокинуть ошибку и показать на UI-слое
                    Log.d(
                        "OrderRepositoryImpl",
                        "getOrdersStream() error: ${e.localizedMessage}"
                    )
                    
                }
            }
        }
        return localDataSource
            .getOrders(user)
            .stateIn(
                scope = scope,
                started = SharingStarted.Lazily,
                initialValue = listOf()
            )
    }
}

Ответы (0 шт):