cashapp / sqldelight

SQLDelight - Generates typesafe Kotlin APIs from SQL
https://cashapp.github.io/sqldelight/
Apache License 2.0
6.14k stars 515 forks source link

Can not add query listener on native/iOS #1390

Closed kuhnroyal closed 5 years ago

kuhnroyal commented 5 years ago

Adding query listeners or using the coroutine extension, which uses query listeners, fails on native/iOS. Kotlin 1.3.40 and the current 1.2.0-SNAPSHOT

The cause seems to be kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.atomicfu.AtomicRef.

kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[EventLoopImpl@3bc36878, Continuation @ $<get-collectToFun>$lambda-0COROUTINE$108]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
Invalid connection: com.apple.coresymbolicationd
        at 0   test.kexe                           0x00000001097e2269 kfun:kotlin.Error.<init>(kotlin.String?;kotlin.Throwable?)kotlin.Error + 25 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:14:5)
        at 1   test.kexe                           0x00000001097e1ad9 kfun:kotlinx.coroutines.CoroutinesInternalError.<init>(kotlin.String;kotlin.Throwable)kotlinx.coroutines.CoroutinesInternalError + 25 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/Exceptions.common.kt:26:98)
        at 2   test.kexe                           0x00000001097e16fe kfun:kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx-coroutines-core(kotlin.Throwable?;kotlin.Throwable?) + 366 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/Dispatched.kt:<unknown>)
        at 3   test.kexe                           0x00000001097e291d kfun:kotlinx.coroutines.DispatchedTask.run() + 1245 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/Dispatched.kt:<unknown>)
        at 4   test.kexe                           0x00000001097e3b83 kfun:kotlinx.coroutines.EventLoopImpl.processNextEvent()kotlin.Long + 323 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/EventLoop.kt:96:16)
        at 5   test.kexe                           0x0000000109912235 kfun:kotlinx.coroutines.BlockingCoroutine.joinBlocking#internal + 437 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:65:44)
        at 6   test.kexe                           0x0000000109911fdd kfun:kotlinx.coroutines.runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>)Generic + 893 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:50:22)
        at 7   test.kexe                           0x0000000109911c10 kfun:kotlinx.coroutines.runBlocking$default(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>;kotlin.Int)Generic + 176 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:33:8)
        at 8   test.kexe                           0x0000000109911ab8 kfun:foo.bar.common.coroutines.runBlocking(kotlin.coroutines.SuspendFunction0<#GENERIC>)Generic + 104 (/foo/bar/common/coroutines/RunBlocking.kt:<unknown>)
        at 9   test.kexe                           0x00000001099119b1 kfun:foo.bar.common.data.GithubRepositoryDatabaseTest.Table should have 2 entries with coroutines() + 97 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:<unknown>)
        at 10  test.kexe                           0x0000000109911948 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.invoke#internal + 24 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 11  test.kexe                           0x0000000109911919 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.$<bridge-UNNN>invoke(#GENERIC)#internal + 25 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 12  test.kexe                           0x000000010990e34d kfun:kotlin.native.internal.test.BaseClassSuite.TestCase.run() + 541 (/Users/teamcity/buildAgent/work/4d622a065c544371/backend.native/build/stdlib/generated/_Collections.kt:97:7)
        at 13  test.kexe                           0x00000001097f851c kfun:kotlin.native.internal.test.TestRunner.run#internal + 1036 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:223:0)
        at 14  test.kexe                           0x00000001097f7a51 kfun:kotlin.native.internal.test.TestRunner.runIteration#internal + 1281 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/system/Timing.kt:33:12)
        at 15  test.kexe                           0x00000001097f72f0 kfun:kotlin.native.internal.test.TestRunner.run()kotlin.Int + 576 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:270:0)
        at 16  test.kexe                           0x00000001097f61e2 kfun:kotlin.native.internal.test.testLauncherEntryPoint(kotlin.Array<kotlin.String>)kotlin.Int + 114 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:19:47)
        at 17  test.kexe                           0x00000001097f6161 kfun:kotlin.native.internal.test.main(kotlin.Array<kotlin.String>) + 17 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:23:5)
        at 18  test.kexe                           0x00000001097f60df Konan_start + 63 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/launcher/kotlin/konan/start.kt:<unknown>)
        at 19  test.kexe                           0x00000001097f5f6e Init_and_run_start + 78
        at 20  libdyld.dylib                       0x000000010bb0e541 start + 1
        at 21  ???                                 0x0000000000000001 0x0 + 1
Caused by: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.atomicfu.AtomicRef@3a5d5f98
        at 0   test.kexe                           0x00000001097bcd27 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 23 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Throwable.kt:21:56)
        at 1   test.kexe                           0x00000001097bcce5 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:5)
        at 2   test.kexe                           0x00000001097bccb5 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:5)
        at 3   test.kexe                           0x00000001097bdfb5 kfun:kotlin.native.concurrent.InvalidMutabilityException.<init>(kotlin.String)kotlin.native.concurrent.InvalidMutabilityException + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:85)
        at 4   test.kexe                           0x00000001099ad410 ThrowInvalidMutabilityException + 256 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:77:11)
        at 5   test.kexe                           0x00000001099c6612 MutationCheck + 50
        at 6   test.kexe                           0x00000001097cb25e kfun:kotlinx.atomicfu.AtomicRef.<set-value>(#GENERIC) + 30 (/opt/buildAgent/work/88b0986a7186d029/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt:17:19)
        at 7   test.kexe                           0x00000001097ca8e6 kfun:kotlinx.atomicfu.AtomicRef.compareAndSet(#GENERIC;#GENERIC)kotlin.Boolean + 118 (/opt/buildAgent/work/88b0986a7186d029/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt:<unknown>)
        at 8   test.kexe                           0x00000001097ca25e kfun:kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath#internal + 462 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:834:21)
        at 9   test.kexe                           0x00000001097ca02a kfun:kotlinx.coroutines.JobSupport.tryMakeCompleting#internal + 218 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:813:16)
        at 10  test.kexe                           0x000000010985f295 kfun:kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx-coroutines-core(kotlin.Any?;kotlin.Int)kotlin.Boolean + 213 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:789:15)
        at 11  test.kexe                           0x000000010985f17d kfun:kotlinx.coroutines.AbstractCoroutine.resumeWith(kotlin.Result<#GENERIC>) + 109 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt:<unknown>)
        at 12  test.kexe                           0x00000001097dddf6 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl.resumeWith(kotlin.Result<kotlin.Any?>) + 646 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt:<unknown>)
        at 13  test.kexe                           0x00000001097e28a3 kfun:kotlinx.coroutines.DispatchedTask.run() + 1123 (/Users/teamcity/buildAgent/work/4d622a065c544371/backend.native/build/stdlib/kotlin/util/Result.kt:151:0)
        at 14  test.kexe                           0x00000001097e3b83 kfun:kotlinx.coroutines.EventLoopImpl.processNextEvent()kotlin.Long + 323 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/EventLoop.kt:96:16)
        at 15  test.kexe                           0x0000000109912235 kfun:kotlinx.coroutines.BlockingCoroutine.joinBlocking#internal + 437 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:65:44)
        at 16  test.kexe                           0x0000000109911fdd kfun:kotlinx.coroutines.runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>)Generic + 893 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:50:22)
        at 17  test.kexe                           0x0000000109911c10 kfun:kotlinx.coroutines.runBlocking$default(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>;kotlin.Int)Generic + 176 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:33:8)
        at 18  test.kexe                           0x0000000109911ab8 kfun:foo.bar.common.coroutines.runBlocking(kotlin.coroutines.SuspendFunction0<#GENERIC>)Generic + 104 (/foo/bar/common/coroutines/RunBlocking.kt:<unknown>)
        at 19  test.kexe                           0x00000001099119b1 kfun:foo.bar.common.data.GithubRepositoryDatabaseTest.Table should have 2 entries with coroutines() + 97 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:<unknown>)
        at 20  test.kexe                           0x0000000109911948 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.invoke#internal + 24 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 21  test.kexe                           0x0000000109911919 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.$<bridge-UNNN>invoke(#GENERIC)#internal + 25 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 22  test.kexe                           0x000000010990e34d kfun:kotlin.native.internal.test.BaseClassSuite.TestCase.run() + 541 (/Users/teamcity/buildAgent/work/4d622a065c544371/backend.native/build/stdlib/generated/_Collections.kt:97:7)
        at 23  test.kexe                           0x00000001097f851c kfun:kotlin.native.internal.test.TestRunner.run#internal + 1036 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:223:0)
        at 24  test.kexe                           0x00000001097f7a51 kfun:kotlin.native.internal.test.TestRunner.runIteration#internal + 1281 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/system/Timing.kt:33:12)
        at 25  test.kexe                           0x00000001097f72f0 kfun:kotlin.native.internal.test.TestRunner.run()kotlin.Int + 576 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:270:0)
        at 26  test.kexe                           0x00000001097f61e2 kfun:kotlin.native.internal.test.testLauncherEntryPoint(kotlin.Array<kotlin.String>)kotlin.Int + 114 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:19:47)
        at 27  test.kexe                           0x00000001097f6161 kfun:kotlin.native.internal.test.main(kotlin.Array<kotlin.String>) + 17 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:23:5)
        at 28  test.kexe                           0x00000001097f60df Konan_start + 63 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/launcher/kotlin/konan/start.kt:<unknown>)
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.coroutines.EventLoopImpl@3bc36878
        at 0   test.kexe                           0x00000001097bcd27 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 23 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Throwable.kt:21:56)
        at 1   test.kexe                           0x00000001097bcce5 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:5)
        at 2   test.kexe                           0x00000001097bccb5 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:5)
        at 3   test.kexe                           0x00000001097bdfb5 kfun:kotlin.native.concurrent.InvalidMutabilityException.<init>(kotlin.String)kotlin.native.concurrent.InvalidMutabilityException + 21 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:85)
        at 4   test.kexe                           0x00000001099ad410 ThrowInvalidMutabilityException + 256 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:77:11)
        at 5   test.kexe                           0x00000001099c6612 MutationCheck + 50
        at 6   test.kexe                           0x00000001097e1a9e kfun:kotlinx.coroutines.EventLoop.<set-useCount>#internal + 30 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/EventLoop.common.kt:23:13)
        at 7   test.kexe                           0x00000001097e180e kfun:kotlinx.coroutines.EventLoop.decrementUseCount(kotlin.Boolean) + 110 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/EventLoop.common.kt:106:13)
        at 8   test.kexe                           0x000000010991286b kfun:kotlinx.coroutines.EventLoop.decrementUseCount$default(kotlin.Boolean;kotlin.Int) + 43 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/EventLoop.common.kt:112:6)
        at 9   test.kexe                           0x0000000109912475 kfun:kotlinx.coroutines.BlockingCoroutine.joinBlocking#internal + 1013 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:61:9)
        at 10  test.kexe                           0x0000000109911fdd kfun:kotlinx.coroutines.runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>)Generic + 893 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:50:22)
        at 11  test.kexe                           0x0000000109911c10 kfun:kotlinx.coroutines.runBlocking$default(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,#GENERIC>;kotlin.Int)Generic + 176 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:33:8)
        at 12  test.kexe                           0x0000000109911ab8 kfun:foo.bar.common.coroutines.runBlocking(kotlin.coroutines.SuspendFunction0<#GENERIC>)Generic + 104 (/foo/bar/common/coroutines/RunBlocking.kt:<unknown>)
        at 13  test.kexe                           0x00000001099119b1 kfun:foo.bar.common.data.GithubRepositoryDatabaseTest.Table should have 2 entries with coroutines() + 97 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:<unknown>)
        at 14  test.kexe                           0x0000000109911948 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.invoke#internal + 24 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 15  test.kexe                           0x0000000109911919 kfun:foo.bar.common.data.$GithubRepositoryDatabaseTest$test$0.$Table should have 2 entries with coroutines$FUNCTION_REFERENCE$24.$<bridge-UNNN>invoke(#GENERIC)#internal + 25 (/foo/bar/common/data/GithubRepositoryDatabase.Test.kt:119:6)
        at 16  test.kexe                           0x000000010990e34d kfun:kotlin.native.internal.test.BaseClassSuite.TestCase.run() + 541 (/Users/teamcity/buildAgent/work/4d622a065c544371/backend.native/build/stdlib/generated/_Collections.kt:97:7)
        at 17  test.kexe                           0x00000001097f851c kfun:kotlin.native.internal.test.TestRunner.run#internal + 1036 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:223:0)
        at 18  test.kexe                           0x00000001097f7a51 kfun:kotlin.native.internal.test.TestRunner.runIteration#internal + 1281 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/system/Timing.kt:33:12)
        at 19  test.kexe                           0x00000001097f72f0 kfun:kotlin.native.internal.test.TestRunner.run()kotlin.Int + 576 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt:270:0)
        at 20  test.kexe                           0x00000001097f61e2 kfun:kotlin.native.internal.test.testLauncherEntryPoint(kotlin.Array<kotlin.String>)kotlin.Int + 114 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:19:47)
        at 21  test.kexe                           0x00000001097f6161 kfun:kotlin.native.internal.test.main(kotlin.Array<kotlin.String>) + 17 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt:23:5)
        at 22  test.kexe                           0x00000001097f60df Konan_start + 63 (/Users/teamcity/buildAgent/work/4d622a065c544371/runtime/src/launcher/kotlin/konan/start.kt:<unknown>)
        at 23  test.kexe                           0x00000001097f5f6e Init_and_run_start + 78
        at 24  libdyld.dylib                       0x000000010bb0e541 start + 1
        at 25  ???                                 0x0000000000000001 0x0 + 1

Any ideas or workarounds?

kpgalligan commented 5 years ago

"Adding query listeners"

Adding a listener on native means it'll freeze the listener you pass in. Listeners in general on native absolutely work, with the caveat that the listener will get frozen when it's passed in (as well as anything it references).

"or using the coroutine extension, which uses query listeners"

I haven't worked on the coroutine extension, but native support should be removed as it won't work properly until there's a multithreaded coroutines implementation for native.

For now, don't attempt to use Flow and native together, unless everything is happening in the same thread (presumably the main one). You can use listeners, but (again) be aware that your listener and everything it touches is frozen.

Live example of multiplatform with a reactive architecture using SqlDelight: https://github.com/touchlab/DroidconKotlin/

Basic pub/sub: https://github.com/touchlab/DroidconKotlin/blob/master/sessionize/lib/src/commonMain/kotlin/co/touchlab/sessionize/db/QueryPub.kt

Experimental example using Badoo's Reaktive: https://github.com/touchlab/DroidconKotlin/blob/kpg/reaktive/sessionize/lib/src/commonMain/kotlin/co/touchlab/sessionize/reaktive/ReaktiveExtensions.kt

Watching the commits to Kotlin/Native proper, there is movement on the basis for MT coroutines, and when that lands a lot of these other frameworks will kind of wither, but for today you need to hand roll things a bit.

kpgalligan commented 5 years ago

Closing. In summary, until Multithreaded coroutines, can't use coroutines or we'd need to refactor how listeners work and (probably) live in the main thread.

lavruk commented 5 years ago

As a workaround can we use the ThreadLocalRef here?

https://github.com/square/sqldelight/blob/master/extensions/coroutines-extensions/src/commonMain/kotlin/com/squareup/sqldelight/runtime/coroutines/FlowExtensions.kt#L38

The modified logic would look like:

fun <T : Any> Query<T>.asFlow(): Flow<Query<T>> = callbackFlow<Query<T>> {

    // using ThreadLocalRef as Query.Listener and all references in it get frozen on native
    // May be removed once fixed in SQLDelight https://github.com/square/sqldelight/issues/1390
    val onNextRef: ThreadLocalRef<() -> Unit> = ThreadLocalRef()
    onNextRef.value = {
        offer(this@asFlow)
    }

    val listener = object : Query.Listener {
        override fun queryResultsChanged() {
            onNextRef.value?.invoke()
        }
    }
    addListener(listener)
    offer(this@asFlow)
    awaitClose {
        removeListener(listener)
        onNextRef.remove()
    }
}.conflate()
mlykotom commented 4 years ago

ThreadLocalRef logic helped .. had to make it actual/expected with this implementation for iOS.