realm / realm-kotlin

Kotlin Multiplatform and Android SDK for the Realm Mobile Database: Build Better Apps Faster.
Apache License 2.0
889 stars 52 forks source link

In case of transaction error ( writeBlocking ) realm doesn't cancel the transaction which lead to "The Realm is already in a write transaction" exception #1615

Closed abdou-gh549 closed 6 months ago

abdou-gh549 commented 6 months ago

How frequently does the bug occur?

Always

Description

When i use writeBlocking for a write transaction and i get "java.lang.IllegalArgumentException: Cannot import an outdated object. Use findLatest(object) to find an up-to-date version of the object in the given context before importing it ". realm doesn't cancel the transaction which lead to the next one to fail because of RLM_ERR_WRONG_TRANSACTION_STATE ( realm already in write transaction )

to handle it in my case i had to add another try catch in my transaction to cancel it in case of unexpected error

when i looked into writeBlocking i found out that the only case when realm cancel the transaction is IllegalStateException

as a library user i think that opening / closing a transaction is realm responsibility, correct me if i am wrong

Stacktrace & log output

12-21 00:38:18.307: W/System.err(8191): java.lang.IllegalArgumentException: Cannot import an outdated object. Use findLatest(object) to find an
12-21 00:38:18.307: W/System.err(8191): up-to-date version of the object in the given context before importing
12-21 00:38:18.307: W/System.err(8191): it.
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.RealmObjectListOperator.insert(RealmListInternal.kt:459)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.ListOperator$DefaultImpls.insertAll(RealmListInternal.kt:220)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.BaseRealmObjectListOperator.insertAll(RealmListInternal.kt:292)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.RealmObjectHelper.assignTyped$io_realm_kotlin_library(RealmObjectHelper.kt:796)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.RealmObjectHelper.assign$io_realm_kotlin_library(RealmObjectHelper.kt:729)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.RealmUtilsKt.copyToRealm(RealmUtils.kt:215)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.RealmUtilsKt.copyToRealm$default(RealmUtils.kt:139)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.InternalMutableRealm$DefaultImpls.copyToRealm(InternalMutableRealm.kt:57)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.SuspendableWriter$WriterRealm.copyToRealm(SuspendableWriter.kt:52)
12-21 00:38:18.307: W/System.err(8191):     at com.omailey.api.helper.realmhelper.RealmWriterHelper$updateMessagesInDb$1.invoke(RealmWriterHelper.kt:223)
12-21 00:38:18.307: W/System.err(8191):     at com.omailey.api.helper.realmhelper.RealmWriterHelper$updateMessagesInDb$1.invoke(RealmWriterHelper.kt:214)
12-21 00:38:18.307: W/System.err(8191):     at com.omailey.api.helper.realmhelper.RealmWriterHelper$writeTTC$1$1.invoke(RealmWriterHelper.kt:2852)
12-21 00:38:18.307: W/System.err(8191):     at com.omailey.api.helper.realmhelper.RealmWriterHelper$writeTTC$1$1.invoke(RealmWriterHelper.kt:2851)
12-21 00:38:18.307: W/System.err(8191):     at io.realm.kotlin.internal.SuspendableWriter$write$2.invokeSuspend(SuspendableWriter.kt:110)
12-21 00:38:18.307: W/System.err(8191):     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12-21 00:38:18.307: W/System.err(8191):     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
12-21 00:38:18.307: W/System.err(8191):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
12-21 00:38:18.307: W/System.err(8191):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
12-21 00:38:18.307: W/System.err(8191):     at java.lang.Thread.run(Thread.java:764)
12-21 00:38:18.310: D/MediaSyncWorker(8191): startWork
12-21 00:38:18.314: D/RealmWriterHelper(8191): unflagAllUploading Medias: 
12-21 00:38:18.336: W/audio_hw_generic(1392): Hardware backing HAL too slow, could only write 0 of 720 frames
12-21 00:38:18.339: D/com.omailey.api.net.http.ApiRequestHandler(8191): onResponse success

12-21 00:38:18.456: D/MonitoringInstr(8191): Handling an uncaught exception thrown on the thread DefaultDispatcher-worker-13.
12-21 00:38:18.456: D/MonitoringInstr(8191): java.lang.IllegalStateException: [RLM_ERR_WRONG_TRANSACTION_STATE]: The Realm is already in a write transaction
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.CoreErrorConverter.asThrowable(CoreErrorConverter.kt:44)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.realmcJNI.realm_begin_write(Native Method)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.realmc.realm_begin_write(realmc.java:465)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.RealmInterop.realm_begin_write(RealmInterop.kt:351)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.WriteTransactionManager$DefaultImpls.beginTransaction(WriteTransactionManager.kt:28)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.SuspendableWriter$WriterRealm.beginTransaction(SuspendableWriter.kt:52)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at io.realm.kotlin.internal.SuspendableWriter$write$2.invokeSuspend(SuspendableWriter.kt:108)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
12-21 00:38:18.456: D/MonitoringInstr(8191):    at java.lang.Thread.run(Thread.java:764)
12-21 00:38:18.456: D/MonitoringInstr(8191):    Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@72fe6c3, Dispatchers.IO]
12-21 00:38:18.457: W/AndroidJUnitRunner(8191): An unhandled exception was thrown by the app.
12-21 00:38:18.457: W/AndroidJUnitRunner(8191): java.lang.IllegalStateException: [RLM_ERR_WRONG_TRANSACTION_STATE]: The Realm is already in a write transaction
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.interop.CoreErrorConverter.asThrowable(CoreErrorConverter.kt:44)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.interop.realmcJNI.realm_begin_write(Native Method)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.interop.realmc.realm_begin_write(realmc.java:465)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.interop.RealmInterop.realm_begin_write(RealmInterop.kt:351)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.WriteTransactionManager$DefaultImpls.beginTransaction(WriteTransactionManager.kt:28)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.SuspendableWriter$WriterRealm.beginTransaction(SuspendableWriter.kt:52)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at io.realm.kotlin.internal.SuspendableWriter$write$2.invokeSuspend(SuspendableWriter.kt:108)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     at java.lang.Thread.run(Thread.java:764)
12-21 00:38:18.457: W/AndroidJUnitRunner(8191):     Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@72fe6c3, Dispatchers.IO]
12-21 00:38:18.458: D/AndroidJUnitRunner(8191): Reporting the crash to an event service.
12-21 00:38:18.458: D/TestEventClient(8191): Reporting process crashed to orchestration test run event service.
12-21 00:38:18.458: I/OrchestrationListener(8191): No test failure has been reported. Report the process crash.
12-21 00:38:18.461: I/AndroidJUnitRunner(8191): Bringing down the entire Instrumentation process.
12-21 00:38:18.462: E/MonitoringInstr(8191): Exception encountered by: Thread[DefaultDispatcher-worker-13,5,main]. Dumping thread state to outputs and pining for the fjords.
12-21 00:38:18.462: E/MonitoringInstr(8191): java.lang.IllegalStateException: [RLM_ERR_WRONG_TRANSACTION_STATE]: The Realm is already in a write transaction
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.CoreErrorConverter.asThrowable(CoreErrorConverter.kt:44)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.realmcJNI.realm_begin_write(Native Method)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.realmc.realm_begin_write(realmc.java:465)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.interop.RealmInterop.realm_begin_write(RealmInterop.kt:351)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.WriteTransactionManager$DefaultImpls.beginTransaction(WriteTransactionManager.kt:28)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.SuspendableWriter$WriterRealm.beginTransaction(SuspendableWriter.kt:52)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at io.realm.kotlin.internal.SuspendableWriter$write$2.invokeSuspend(SuspendableWriter.kt:108)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
12-21 00:38:18.462: E/MonitoringInstr(8191):    at java.lang.Thread.run(Thread.java:764)

Can you reproduce the bug?

Always

Reproduction Steps

Version

1.10.0

What Atlas App Services are you using?

Local Database only

Are you using encryption?

Yes

Platform OS and version(s)

android API 29

Build environment

Android Studio version: Giraffe

rorbech commented 6 months ago

Hi @abdou-gh549. Thanks for the report. I have created https://github.com/realm/realm-kotlin/pull/1621 to fix it.