Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does Realm creation happen on UI Thread? #1675

Closed
mahmed1987 opened this issue Mar 5, 2024 · 6 comments
Closed

Does Realm creation happen on UI Thread? #1675

mahmed1987 opened this issue Mar 5, 2024 · 6 comments

Comments

@mahmed1987
Copy link

mahmed1987 commented Mar 5, 2024

How frequently does the bug occur?

Always

Description

I have this very simple class that handles realm initialization and access


import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.TypedRealmObject
import kotlinx.coroutines.flow.map
import kotlin.reflect.KClass

class Database {
    private val db: Realm

    init {
        val config = RealmConfiguration.create(schema = setOf(LocalUser::class))
        db = Realm.open(config)
    }



    suspend fun add(manga: RealmObject) {
        db.write {
            copyToRealm(manga)
        }
    }

    fun <T : TypedRealmObject> queryFirstLive(clazz: KClass<T>) =
        db.query(clazz).first().asFlow().map { it.obj }

    suspend fun deleteAll() {
        db.write {
            deleteAll()
        }
    }

    fun close() {
        if (!db.isClosed())
            db.close()
    }

}

If i use StrictMode like this in my Main Application class

 private fun setupStrictMode() {
        val policy = ThreadPolicy.Builder()
            .detectDiskReads()
            .detectDiskWrites()
            .penaltyDeath() // This will cause the app to crash on violation
            .build()
        StrictMode.setThreadPolicy(policy)
    }

It informs me that realm creation (in the init block) is violating the diskWrite policy . While it shows absolutely no visible performance effects on the app , i was just wondering if I am doing things right ?

In the realm documentation too I do not find any examples in which the realm creation is offloaded into some background thread.

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

No response

Version

1.11.1

What Atlas App Services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

Android 13

Build environment

Android Studio version: ... Hedgehog
Android Build Tools version: ...
Gradle version: ... 8.2.2

Copy link

sync-by-unito bot commented Mar 5, 2024

➤ PM Bot commented:

Jira ticket: RKOTLIN-1028

@rorbech
Copy link
Contributor

rorbech commented Mar 6, 2024

Hi @mahmed1987. Realm.open will open the file and potentially make changes to the file (updating metadata, compaction, etc.). This is usually a very quick step, but could be lengthly if doing heavy compaction or awaiting initial synchronization from server for synchronized realm. So I guess it depends on your use cases.

The realm instance can be shared across threads, so you can just offload this to a background thread, if needed.

@rorbech
Copy link
Contributor

rorbech commented Mar 6, 2024

And just to answer the question from the title. The realm is initialized on the thread where you call Realm.open, so there is nothing explicitly scheduled on the UI thread.

@sync-by-unito sync-by-unito bot closed this as completed Mar 6, 2024
@mahmed1987
Copy link
Author

mahmed1987 commented Mar 6, 2024

thank you for your response .

Can you point me to some sample code in which the realm's initialization is conducted on a different thread or i mean a Dispatchers.IO/Main in Coroutines ?

Actually none of the samples I have found , (for kotlin - multiplatform atleast) , do it. And the lack of mention of this on your official docs pointed me towards this assumption too that it is safe to create realm on UI Thread .

I do not used a server synced realm , however I am worried about "compaction" that you speak off .

So yeah , how would it look like if we create realm on a different CoroutineScope ? . I actually tried a solution but it lead me to different problems .

class Database {
    private var lateinit db: Realm

    init {
CoroutineScope(Dispatchers.IO)
{
        val config = RealmConfiguration.create(schema = setOf(LocalUser::class))
        db = Realm.open(config)
}
    }



    suspend fun add(manga: RealmObject) {
        db.write {
            copyToRealm(manga)
        }
    }

    fun <T : TypedRealmObject> queryFirstLive(clazz: KClass<T>) =
        db.query(clazz).first().asFlow().map { it.obj }

    suspend fun deleteAll() {
        db.write {
            deleteAll()
        }
    }

    fun close() {
        if (!db.isClosed())
            db.close()
    }

}

Here we run into a possible lateinit exception , in which some process tries to access db object (via functions like add()), even though it is not yet created

@rorbech
Copy link
Contributor

rorbech commented Mar 6, 2024

Yes, you would need to synchronize initialization with other operations on the realm. A very simple approach could be to initializate the realm in a job and guard operations on it with a join.

Something like:

init {
    job = CoroutineScope(Dispatchers.IO).launch {
        val config = RealmConfiguration.create(schema = setOf(LocalUser::class))
        db = Realm.open(config)
    }
}

susped fun add() {
   job.join()
   db.write { ... }
}

This is however not a realm specific question, so you might want to search other resources like Stack Overflow or the MongoDB Forum (if questions are in the context of MongoDB/Realm).

@mahmed1987
Copy link
Author

Hey , actually I did scan the internet for this . There is NOT A SINGLE resource that addresses this and I too wouldn't have ever found out if I hadn't turned on the StrictMode.

All the tutorials , all resources , give a very straight forward implementation of realm .

You can appreciate the complexity and awkwardness of code if we attempt to create realm on a background thread .

I am confused as to why aren't more people talking about it . And whether I should mark this issue up in my next standup or let it be .

I hope this isn't a ticking time bomb kinda situation

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants