Is there way to observe changes in SqlDelight via ...
# squarelibraries
r
Is there way to observe changes in SqlDelight via Flow like Room supports? I could see there is an extension library which can turn the queries to. flow , but still I am not able to get the result This is how I am setting up flow in SqlDelight
Copy code
override fun observeAll(): Flow<List<NetworkRequest>> {
        return networkRequestQueries.selectAll().asFlow().map { query ->
            query.executeAsList().map {
                NetworkRequest(
                    it.host,
                    it.path,
                    it.method,
                    requestTime = it.request_time,
                    responseCode = it.response_code,
                    responseTimeTaken = it.response_time_taken,
                    isFailedByFlaker = it.is_failed_by_flaker
                )
            }
        }
    }
It only gives me the result only first time invocations Update I tried this as well still its not emitting values after insertions are made to DB
Copy code
override fun observeAll(): Flow<List<NetworkRequest>> {
        return networkRequestQueries.selectAll(
            mapper = { _, host: String, path: String, method: String, request_time: Long, response_code: Long, response_time_taken: Long, is_failed_by_flaker: Boolean ->
                NetworkRequest(
                    host,
                    path,
                    method,
                    request_time,
                    response_code,
                    response_time_taken,
                    is_failed_by_flaker
                )

            }
        ).asFlow().mapToList(<http://Dispatchers.IO|Dispatchers.IO>)
    }
FYI I am on latest 2.0.0 CAUSE Found the cause, Observing and Insertion DB instances were different that why its happening
✔️ 1
b
Copy code
.asFlow()
    .mapToList(ioContext)
r
I tried this as well still does not work
b
Can you explain what is happening instead?
r
It is not emitting values after first emission
It only emits all the data for first time, but after db insertion it does not emit it again
b
Did you write a test you could share?
r
I dont have the test. but repository is open source if that helps
b
Another idea would be that you disposed the stream?
r
I don't think so its under ViewModel and stays there
Copy code
private fun observeAllRequests() {
        val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
            Log.e("FlakerViewModel", "Error loading all requests", throwable)
        }
        viewModelScope.launch(coroutineExceptionHandler) {
            flakerRepo.observeAllRequests()
                .collectLatest {
                    Log.d("FUI", "collect list: ${it.size}")
                    val uiList: List<NetworkRequestUi> = it
                        .map { NetworkRequestUi.NetworkRequestItem(it) }
                        .groupBy { it.networkRequest.requestTime }
                        .entries
                        .flatMap { (dateLong, items) ->
                            
                            listOf(NetworkRequestUi.DateItem(dateLong.toString())) + items
                        }
                    _viewStateFlow.emit(_viewStateFlow.value.copy(networkRequests = uiList))
                }
        }
    }'
b
I’d write a test on the repo to narrow down the scope.
r
I have the test on Repo, but there I am having fake DataSource to provide the data here is the test
Copy code
@Test
    fun `GIVEN networkRequestRepo has data WHEN observeAllRequests() called THEN it should return same data`() {
        runBlocking {
            val flakerRepo =
                FlakerRepo(
                    fakeContext,
                    testNetworkRequestRepoProvider,
                    testFlakerPrefsProvider,
                    mainDispatcherRule.testDispatcher
                )

            flakerRepo.observeAllRequests().test {
                assert(awaitItem() == fakeFlakerDataList)
                assert(awaitItem() == fakeFlakerDataList.subList(0, fakeFlakerDataList.size - 1))
                cancelAndIgnoreRemainingEvents()
            }
        }
    }
and here is the fake data source for Unit Test
Copy code
private val testNetworkRequestRepoProvider = object : NetworkRequestRepoProvider(fakeContext) {

        val fakeDataRepo = object : NetworkRequestRepo {
            override fun selectAll(): List<NetworkRequest> {
                return fakeFlakerDataList
            }

            override fun insert(networkRequest: NetworkRequest) = Unit

            override fun observeAll(): Flow<List<NetworkRequest>> {
                return flowOf(fakeFlakerDataList, fakeFlakerDataList.subList(0, fakeFlakerDataList.size - 1))
            }
        }

        override fun provide(): NetworkRequestRepo {
            return fakeDataRepo
        }
    }
b
Got it. I meant using the database directly and write a test to confirm it is emitting or not.
r
Let me check that I thought to do that later in Unit test. Let me see
Is it possible you @Benoit Quenaudon to give any working example for this? may be an an example. so That I can verify
Found the cause, Observing and Insertion DB instances were different that why its happening
b
Happy you found it