realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.75k forks source link

Flexible Sync initialSubscriptions should run the first time only #7656

Open nhachicha opened 2 years ago

nhachicha commented 2 years ago

How frequently does the bug occur?

All the time

Description

initialSubscriptions block runs on the subsequent starts of the App which causes the subscriptions to be added which throws

        app.loginAsync(Credentials.anonymous()) {
            if (it.isSuccess)  {
                user = it.get()
                val config = SyncConfiguration.Builder(user)
                    .initialSubscriptions { realm, subscriptions ->

                        subscriptions.add(
                            Subscription.create(
                                "My Bookshelf",
                                realm.where(Bookshelf::class.java)
                            )
                        )

                        subscriptions.add(
                            Subscription.create(
                                "All Book",
                                realm.where(Book::class.java)
                            )
                        )

                        subscriptions.add(
                            Subscription.create(
                                "All Authors",
                                realm.where(Author::class.java)
                            )
                        )
                        subscriptions.add(
                            Subscription.create(
                                "All UserBook",
                                realm.where(UserBook::class.java)
                            )
                        )
                    }
                    .waitForInitialRemoteData()
                    .build()
                Realm.getInstanceAsync(config, object : Callback() {
                    override fun onSuccess(syncRealm: Realm) {
                        realm = syncRealm
                        _isSyncReady.value = true
                   }})

Stacktrace & log output

03-10 21:34:07.580 13996 14040 E REALM_JNI: jni: ThrowingException 1, Subscription could not be added because it already existed, .
03-10 21:34:07.580 13996 14040 E REALM_JNI: Exception has been thrown: Illegal Argument: Subscription could not be added because it already existed
03-10 21:34:07.586 13996 14040 E REALM_JAVA: java.lang.IllegalArgumentException: Illegal Argument: Subscription could not be added because it already existed
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.nativeInsertOrAssign(Native Method)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.addSubscription(OsMutableSubscriptionSet.java:49)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.add(OsMutableSubscriptionSet.java:38)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.example.bookshelf.RealmDatabase.init$lambda-1$lambda-0(RealmDatabase.kt:89)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.example.bookshelf.RealmDatabase.$r8$lambda$pPIJyIDfcis7MGgVcDWegtLQiQA(Unknown Source:0)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.example.bookshelf.RealmDatabase$$ExternalSyntheticLambda1.configure(Unknown Source:0)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.SyncObjectServerFacade$1.update(SyncObjectServerFacade.java:304)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.objectstore.OsSubscriptionSet.update(OsSubscriptionSet.java:178)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.SyncObjectServerFacade.downloadInitialFlexibleSyncData(SyncObjectServerFacade.java:301)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:473)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:422)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.RealmCache$CreateRealmRunnable.run(RealmCache.java:249)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at io.realm.internal.async.BgPriorityRunnable.run(BgPriorityRunnable.java:34)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:    at java.lang.Thread.run(Thread.java:919)
03-10 21:34:07.586 13996 14040 E REALM_JAVA:
03-10 21:34:07.586 13996 14040 E REALM_JAVA: `CreateRealmRunnable` failed.
03-10 21:34:07.697 13996 13996 D AndroidRuntime: Shutting down VM
03-10 21:34:07.699 13996 13996 E AndroidRuntime: FATAL EXCEPTION: main
03-10 21:34:07.699 13996 13996 E AndroidRuntime: Process: io.realm.example.bookshelf, PID: 13996
03-10 21:34:07.699 13996 13996 E AndroidRuntime: io.realm.exceptions.RealmException: Exception happens when initializing Realm in the background thread.
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.BaseRealm$InstanceCallback.onError(BaseRealm.java:1058)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.Realm$Callback.onError(Realm.java:2061)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.RealmCache$CreateRealmRunnable$2.run(RealmCache.java:303)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at android.os.Handler.handleCallback(Handler.java:883)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:100)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:214)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:7356)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
03-10 21:34:07.699 13996 13996 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: Illegal Argument: Subscription could not be added because it already existed
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.nativeInsertOrAssign(Native Method)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.addSubscription(OsMutableSubscriptionSet.java:49)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.objectstore.OsMutableSubscriptionSet.add(OsMutableSubscriptionSet.java:38)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.example.bookshelf.RealmDatabase.init$lambda-1$lambda-0(RealmDatabase.kt:89)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.example.bookshelf.RealmDatabase.$r8$lambda$pPIJyIDfcis7MGgVcDWegtLQiQA(Unknown Source:0)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.example.bookshelf.RealmDatabase$$ExternalSyntheticLambda1.configure(Unknown Source:0)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.SyncObjectServerFacade$1.update(SyncObjectServerFacade.java:304)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.objectstore.OsSubscriptionSet.update(OsSubscriptionSet.java:178)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.SyncObjectServerFacade.downloadInitialFlexibleSyncData(SyncObjectServerFacade.java:301)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:473)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:422)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.RealmCache$CreateRealmRunnable.run(RealmCache.java:249)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at io.realm.internal.async.BgPriorityRunnable.run(BgPriorityRunnable.java:34)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
03-10 21:34:07.699 13996 13996 E AndroidRuntime:    at java.lang.Thread.run(Thread.java:919)
03-10 21:34:07.699 13159 13159 I GoogleInputMethodService: GoogleInputMethodService.onFinishInput():3210
03-10 21:34:07.700 13996 14036 I OpenGLRenderer: Davey! duration=1023ms; Flags=0, IntendedVsync=155469373454252, Vsync=155470140120888, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=155470149052428, AnimationStart=155470149109428, PerformTraversalsStart=155470357014428, DrawStart=155470382723428, SyncQueued=155470390499428, SyncStart=155470390777428, IssueDrawCommandsStart=155470390847428, SwapBuffers=155470391936428, FrameCompleted=155470397143428, DequeueBufferDur

Can you reproduce the bug?

Yes, always

Reproduction Steps

No response

Version

10.10.1

What SDK flavour are you using?

MongoDB Realm (i.e. Sync, auth, functions)

Are you using encryption?

No, not using encryption

Platform OS and version(s)

Android API29 x86_64

Build environment

No response

colin-ifit commented 1 year ago

I ran into this issue too. The workaround that seems to work for me is to use subscriptions.addOrUpdate(...) instead of subscriptions.add(...).

hkchakladar commented 7 months ago

subscriptions.addOrUpdate(...) is this the official method?

hkchakladar commented 7 months ago

On furthur reading/testing, it seems that subscriptions.addOrUpdate(...) is not a usable workaround. It doesn't work when the device is offline and in blocks the initialization of the Realm.getInstance()

So issue still persists.