Store icon indicating copy to clipboard operation
Store copied to clipboard

[BUG] Calling store.get() in RoomDatabase.withTransaction will encounter a deadlock

Open yaoandy107 opened this issue 3 years ago • 6 comments

Describe the bug When I call store.get() in the RoomDatabase.withTransaction {} and the store trigger the writer to write data into the database, a deadlock will occur. Everything is fine if the writer does not trigger or calling the store.get() outside the withTransaction {}.

To Reproduce

  1. clear the Room's table that the Store used
  2. call store.get() inside the RoomDatabase.withTransaction {}

Sample code (Full sample):

viewLifecycleOwner.lifecycleScope.launch {
    appDatabase.forumDao().deleteAll()
    // The transaction work fine if uncomment the line below
    // forumStore.get(ForumKey(id = "1"))
    appDatabase.withTransaction {
        Log.d("TEST", "Start transaction")
        forumStore.get(ForumKey(id = "1"))
        Log.d("TEST", "End transaction")
    }
}

Expected behavior

  1. According to the sample above, either the "End transaction" should print or the error log should appear

Smartphone (please complete the following information):

  • Device: Emulator Pixel_4_API_33
  • OS: Android 13
  • Store Version: 4.0.5

yaoandy107 avatar Sep 27 '22 09:09 yaoandy107

Thank you for reporting and including a sample ❤️. I can take a look this week and let you know a fix/suggestion. My initial thinking is the transaction is locking writing to the db within your block. Without writing we can't read.

digitalbuddha avatar Sep 27 '22 12:09 digitalbuddha

This looks related. https://issuetracker.google.com/issues/120854786 Seems like there is a runInTransaction function when working with suspend and transactions in room

digitalbuddha avatar Sep 27 '22 12:09 digitalbuddha

Do you mind trying the new transaction api and reporting back if it works?

digitalbuddha avatar Sep 27 '22 12:09 digitalbuddha

Thanks for your fast reply. The runInTransaction() can't support suspend function, so it can't replace withTransaction(). Besides, the withTransaction() is the new API introduced in the issue you posted above.

yaoandy107 avatar Sep 27 '22 13:09 yaoandy107

I find out that the KDoc of withTransaction() has mentioned that it should use the same coroutineScope that receive by the suspending block to perform blocking database operation. So I guess it's the limitation of Room which let the usage of Store inside withTransaction() impossible.

Screen Shot 2022-09-27 at 9 52 25 PM

yaoandy107 avatar Sep 27 '22 13:09 yaoandy107

I'm going to keep this issue open as we are currently rewriting some store internals for a Store5 major release. Let me think about how to solve this in a generic manner.

digitalbuddha avatar Sep 27 '22 14:09 digitalbuddha