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

Realm Flexible Sync - Syncs all data twice #1472

Closed
gauravbordoloi opened this issue Aug 1, 2023 · 8 comments
Closed

Realm Flexible Sync - Syncs all data twice #1472

gauravbordoloi opened this issue Aug 1, 2023 · 8 comments
Assignees

Comments

@gauravbordoloi
Copy link

gauravbordoloi commented Aug 1, 2023

How frequently does the bug occur?

Always

Description

When I first open realm with flexible sync, it syncs all the data. If I close it and open it for the 2nd time, it again resyncs the whole data. And this only happens for the 2nd time. From 3rd time onwards, it works as expected.

My Realm Code -

class DbModule(private val configPreferences: ConfigPreferences) {

    companion object {

        private const val DB_NAME = "homedrop-test.db.realm"
        private val DB_SCHEMAS = setOf(
            EmployeeModel::class,
            PasswordModel::class,
            KycModel::class,
            EmployeeSalaryDetail::class,
            EmployeeSalaryAdvance::class,
            PaymentAccountModel::class,
            EmployeeSalaryAdvanceTransaction::class,
            PermissionRoleModel::class,
            SupplierModel::class,
            AddressModel::class,
            ProductModel::class,
            MetricModel::class,
            TypeModel::class,
            CategoryModel::class,
            BrandModel::class,
            CustomerModel::class,
            DiscountModel::class,
            PaymentTransactionModel::class,
            PurchaseModel::class,
            PurchaseProductModel::class,
            SaleModel::class,
            SaleProductModel::class,
            ExpenseModel::class,
            ManualDiscountModel::class
        )

    }

    private var user: User? = null
    private var realm: Realm? = null
    private var dbLock = Mutex()
    private var app: App

    init {
        app = provideApp()
    }

    private fun provideApp(): App {
        return App.create(
            AppConfiguration.Builder(BuildConfig.REALM_APP_ID).build()
        )
    }

    private fun provideCredential(configPreferences: ConfigPreferences): Credentials {
        return Credentials.jwt(configPreferences.getAdminToken())
    }

    suspend fun getRealmUser(): User {
        if (user == null) {
            user = provideRealmUser(app, provideCredential(configPreferences))
        }
        return user!!
    }

    suspend fun getRealm(waitForSync: Boolean = false): Realm {
        if (realm == null) {
            dbLock.withLock {
                if (realm == null) {
                    initRealm(waitForSync)
                }
            }
        }
        return realm!!
    }

    suspend fun initRealm(waitForSync: Boolean) {
        val syncConfiguration = provideSyncConfiguration(getRealmUser())
        measureExecutionOfSuspend("db_sync") {
            realm = Realm.open(syncConfiguration).also {
                if (waitForSync) {
                    val waitResult = it.subscriptions.waitForSynchronization()
                    Log.e("initRealm", "waitForSynchronization - $waitResult")
                }
            }
        }
    }

    private suspend fun provideRealmUser(app: App, credentials: Credentials): User {
        val user = app.currentUser
        if (user != null && user.profileAsBsonDocument()["userId"]?.asString()?.value == configPreferences.getUid()) {
            return user
        }
        return app.login(credentials)
    }

    private fun provideSyncConfiguration(user: User): SyncConfiguration {
        return SyncConfiguration.Builder(user, DB_SCHEMAS)
            .name(DB_NAME)
            .initialSubscriptions { realm ->
                add(realm.query(BrandModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(CategoryModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(CustomerModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(DiscountModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(EmployeeModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(ExpenseModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(ProductModel::class, "store_id == $0", configPreferences.getUid()))
                add(
                    realm.query(
                        PermissionRoleModel::class,
                        "store_id == $0",
                        configPreferences.getUid()
                    )
                )
                add(realm.query(PurchaseModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(SaleModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(SupplierModel::class, "store_id == $0", configPreferences.getUid()))
                add(realm.query(TypeModel::class))
                add(realm.query(BrandModel::class, "store_id == $0", "GLOBAL"))
                add(realm.query(CategoryModel::class, "store_id == $0", "GLOBAL"))
            }
            .errorHandler { session, error ->
                run {
                    Log.e("syncError", "syncError", error)
                }
            }
            .build()
    }

}

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

No response

Version

1.10.2

What Atlas App Services are you using?

Both Atlas Device Sync and Atlas App Services

Are you using encryption?

No

Platform OS and version(s)

Android, All versions

Build environment

No response

@cmelchior
Copy link
Contributor

Hi @gauravbordoloi When you say it resyncs the data again. How are you detecting that?

@gauravbordoloi
Copy link
Author

gauravbordoloi commented Aug 2, 2023

Hi @cmelchior

After first time sync, I am checking the item count of ProductModel collection which was ~ 15.5k

After 2nd time open, with same query it shows me an item count of 0, and after an interval (Realm syncs data again), the item count gradually increases from 0 to 15.5k (with batches), meaning it's syncing the data again

From 3rd time this behaviour doesn't occur

@cmelchior
Copy link
Contributor

Hmm, interesting. Judging from the code, it looks fine. Are you 100% sure it is the same user being returned the 2nd time around and that configPreferences.getUid() returns the same UUID?

@gauravbordoloi
Copy link
Author

gauravbordoloi commented Aug 2, 2023

Yes @cmelchior , that was my first doubt, so logged the same and found out it was the same user.
In case you want to find out more, I can give you a access for the repo.

@gauravbordoloi
Copy link
Author

Hi @cmelchior Any lead on this?

@J-Dago
Copy link

J-Dago commented Oct 6, 2023

Hi, I have had a similar (or same) issue. I saw a duplicate set of files being created on my device the second time I was running my app. At first I was not setting the name on the SyncConfiguration.Builder, so it was using the default one, and it caused the issue. I then tried setting it, and now the issue was gone. I see that, you are also setting the name, but you have a .realm in the end. I have just tried to add that to my name, and now it duplicates again. So perhaps you can try and remove the .realm, from your DB_NAME and see if it works?

@cmelchior
Copy link
Contributor

cmelchior commented Oct 6, 2023

Okay, I'm able to reproduce this now. It only happens after an app restart and if the realm file name ends with .realm...which the default name does. It looks like a Realm Core bug, but I'm looking for a fix.

It is possible to work around it by setting a custom name on the SyncConfiguration that doesn't end with .realm .e.g. SynConfiguration.Builder(user, schema).name("default").build()

@cmelchior
Copy link
Contributor

This was fixed in Realm Core 13.23.1, which was released in Realm Kotlin 1.12.0

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 18, 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

3 participants