Skip to content

Commit

Permalink
Update DoorFlow to avoid using launch.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedawson committed Feb 2, 2023
1 parent 1874508 commit bc1c3a4
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ plugins {


group 'com.github.UstadMobile.door'
version '0.0.63l'
version '0.0.63m'

ext.localProperties = new Properties()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,42 @@ package com.ustadmobile.door.flow

import com.ustadmobile.door.room.InvalidationTrackerObserver
import com.ustadmobile.door.room.RoomDatabase
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow

/**
* Used by generated code to return a flow that will emit a value when collected for the first time, and will continue
* to emit updates whenever the given tables are invalidated.
*
* It is used by generated code. It can also be used to consume other queries as a flow.
*
* @receiver The database, used to listen for table changes
* @param tables the list of tables that should be monitored for changes
* @param block generated function that will run the query itself
* @return Kotlin Flow that will automatically emit the result of the block, and will emit the result of the block again
* whenever the tables are changed.
*/
@Suppress("unused") //This function is used by generated code
fun <T> RoomDatabase.doorFlow(tables: Array<String>, block: suspend () -> T): Flow<T> = callbackFlow {
fun <T> RoomDatabase.doorFlow(
tables: Array<String>,
block: suspend () -> T
): Flow<T> = callbackFlow {
val invalidationEventChannel = Channel<Boolean>(Channel.CONFLATED)
val invalidationTrackerObserver = object: InvalidationTrackerObserver(tables) {
override fun onInvalidated(tables: Set<String>) {
this@callbackFlow.launch {
trySend(block())
}
invalidationEventChannel.trySend(true)
}
}

this@doorFlow.getInvalidationTracker().addObserver(invalidationTrackerObserver)

trySend(block())
getInvalidationTracker().addObserver(invalidationTrackerObserver)
invalidationEventChannel.trySend(true)

awaitClose {
this@doorFlow.getInvalidationTracker().removeObserver(invalidationTrackerObserver)
try {
for(evt in invalidationEventChannel) {
trySend(block())
}
}finally {
invalidationEventChannel.close()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.ustadmobile.lib.annotationprocessor.core

import com.ustadmobile.door.DatabaseBuilder
import com.ustadmobile.door.DoorDatabaseCallbackSync
import com.ustadmobile.door.DoorSqlDatabase
import db2.ExampleDatabase2
import org.junit.Test
import kotlin.test.assertEquals

class TestDatabaseBuilderCallback {

class CreateEntityCallback: DoorDatabaseCallbackSync {
override fun onCreate(db: DoorSqlDatabase) {
db.execSQL("INSERT INTO ExampleEntity2(uid, name, someNumber, checked, rewardsCardNumber)" +
"VALUES (1, 'Bob', 5, 0, 42)")
}

override fun onOpen(db: DoorSqlDatabase) {
//Do nothing
}
}

@Test
fun givenEntityInsertedByOnCreateCallback_whenDbOpened_thenShouldBeRetrievable() {
val exampleDb2 = DatabaseBuilder.databaseBuilder( ExampleDatabase2::class, "jdbc:sqlite::memory:")
.addCallback(CreateEntityCallback())
.build()

val createdOnCallback = exampleDb2.exampleDao2().findByUid(1)
assertEquals(42, createdOnCallback?.rewardsCardNumber ?: -1,
"Found entity that was created by insert using callback")
}

}

0 comments on commit bc1c3a4

Please sign in to comment.