Skip to content

Commit 87cffaf

Browse files
Merge branch 'call-in-tx-coroutine' into 'dev'
Add BoxStore.awaitCallInTx suspend function See merge request objectbox/objectbox-java!107
2 parents fefba22 + 82451da commit 87cffaf

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ buildscript {
2222
essentials_version = '3.1.0'
2323
junit_version = '4.13.2'
2424
mockito_version = '3.8.0'
25-
kotlin_version = '1.5.0'
26-
coroutines_version = '1.5.0'
25+
kotlin_version = '1.6.0'
26+
coroutines_version = '1.6.0-RC'
2727
dokka_version = '1.4.32'
2828

2929
println "version=$ob_version"

objectbox-kotlin/src/main/kotlin/io/objectbox/kotlin/BoxStore.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ package io.objectbox.kotlin
1818

1919
import io.objectbox.Box
2020
import io.objectbox.BoxStore
21+
import java.util.concurrent.Callable
22+
import kotlin.coroutines.resume
23+
import kotlin.coroutines.resumeWithException
24+
import kotlin.coroutines.suspendCoroutine
2125
import kotlin.reflect.KClass
2226

2327

@@ -27,3 +31,23 @@ inline fun <reified T> BoxStore.boxFor(): Box<T> = boxFor(T::class.java)
2731
/** Shortcut for `BoxStore.boxFor(Entity::class.java)`. */
2832
@Suppress("NOTHING_TO_INLINE")
2933
inline fun <T : Any> BoxStore.boxFor(clazz: KClass<T>): Box<T> = boxFor(clazz.java)
34+
35+
/**
36+
* Wraps [BoxStore.callInTxAsync] in a coroutine that suspends until the transaction has completed.
37+
* Likewise, on success the return value of the given [callable] is returned, on failure an exception is thrown.
38+
*
39+
* Note that even if the coroutine is cancelled the callable is always executed.
40+
*
41+
* The callable (and transaction) is submitted to the ObjectBox internal thread pool.
42+
*/
43+
suspend fun <V : Any> BoxStore.awaitCallInTx(callable: Callable<V?>): V? {
44+
return suspendCoroutine { continuation ->
45+
callInTxAsync(callable) { result, error ->
46+
if (error != null) {
47+
continuation.resumeWithException(error)
48+
} else {
49+
continuation.resume(result)
50+
}
51+
}
52+
}
53+
}

tests/objectbox-java-test/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ dependencies {
5454
}
5555

5656
testImplementation "junit:junit:$junit_version"
57+
// To test Coroutines
58+
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version")
5759
// To test Kotlin Flow
5860
testImplementation 'app.cash.turbine:turbine:0.5.2'
5961
}

tests/objectbox-java-test/src/test/java/io/objectbox/BoxStoreTestK.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package io.objectbox
22

3+
import io.objectbox.kotlin.awaitCallInTx
34
import io.objectbox.kotlin.boxFor
5+
import kotlinx.coroutines.ExperimentalCoroutinesApi
6+
import kotlinx.coroutines.test.runTest
47
import org.junit.Assert.assertEquals
58
import org.junit.Test
69

710

8-
class BoxStoreTestK: AbstractObjectBoxTest() {
11+
class BoxStoreTestK : AbstractObjectBoxTest() {
912

1013
/**
1114
* This is mostly to test the expected syntax works without errors or warnings.
@@ -20,4 +23,23 @@ class BoxStoreTestK: AbstractObjectBoxTest() {
2023
val box2 = store.boxFor(TestEntity::class)
2124
assertEquals(boxJavaApi, box2)
2225
}
26+
27+
@ExperimentalCoroutinesApi
28+
@Test
29+
fun awaitCallInTx() {
30+
val box = store.boxFor<TestEntity>()
31+
runTest {
32+
// put
33+
val id = store.awaitCallInTx {
34+
box.put(createTestEntity("Hello", 1))
35+
}
36+
assertEquals(1, id!!)
37+
38+
// get
39+
val note = store.awaitCallInTx {
40+
box.get(id)
41+
}
42+
assertEquals("Hello", note!!.simpleString)
43+
}
44+
}
2345
}

0 commit comments

Comments
 (0)