Partial Sync never resolves

cloud

#1

I’m using Realm Cloud for my Android project, and have it set up currently where each user has a User parent Realm object that contains lists of data for that user. When I go to fetch that user from the cloud if I’m using partial sync the user never becomes valid (user.isValid() never returns true), whereas if I have the exact same code other than simply specifying fullSynchronization when building the config the user is initially invalid but updates with the proxy in short order.

This only thing that changes is the below:

Realm.setDefaultConfiguration(SyncUser.current().createConfiguration("$REALM_BASE_URL/default2").fullSynchronization().build())

For partial sync I simply remove the fullsync method as the default is partial.

My getUser method looks like this:

fun getUser(realm: Realm, changeListener: RealmChangeListener<User>? = null): User {
        val user = realm.where(User::class.java).equalTo("userId", FirebaseAuth.getInstance().currentUser!!.uid).findFirstAsync()
        if (changeListener != null) {
            user.addChangeListener(changeListener::onChange)
        }
        return user
    }

Note the change listener will be called when using partial or full sync once the query resolves (presumably that’s what’s happening at least, it’s fired off shortly after in either case), it’s just that in partial sync the user I get back isn’t valid, while on full sync it is.

Any ideas what I’m doing wrong here? Thanks!


#2

Was this a bad question (in that I’m doing something stupid that’s well-documented somewhere and/or I haven’t provided enough information to assist)?


#3

@chronofar Please always share the logs when you are having an issue like this - likely this has the answer. I would guess that your Realm is of full type that is for FullSync and you need to convert it to reference to use it for partial sync. You can change to reference by clicking on the Realm in Studio and click the Upgrade button


#4

@ianward thanks! What level of logs do you need? The realm is of reference type. I just switched back to Partial in app and here are the logs (“all”) when I open the app:

The Realm Object Server proxy has 3 open connections to the sync server
3:03:42 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:18,“unknown”:4,“total”:70}
3:03:51 PM
127.0.0.1 - GET /realms/files/%2F__admin?shouldCreate=true&realmType=full HTTP/1.1 200 74 - 0.769 ms
http3:03:58 PM
100.96.2.59 - POST /auth HTTP/1.1 200 787 - 5.466 ms
http3:03:58 PM
127.0.0.1 - GET /realms/files/%2F__admin?shouldCreate=true&realmType=full HTTP/1.1 200 74 - 1.091 ms
http3:03:59 PM
100.96.2.59 - POST /auth HTTP/1.1 200 787 - 7.152 ms
http3:03:59 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:19,“unknown”:4,“total”:71}
3:04:11 PM
127.0.0.1 - GET /health?thisInstance=true HTTP/1.1 200 20 - 0.487 ms
http3:04:17 PM
100.96.2.59 - GET /health HTTP/1.1 200 20 - 2.156 ms
http3:04:17 PM
100.96.23.155 - POST /auth HTTP/1.1 200 794 - 2.695 ms
http3:04:17 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:18,“unknown”:4,“total”:70}
3:04:21 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:19,“unknown”:4,“total”:71}
3:04:41 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:18,“unknown”:4,“total”:70}
3:04:51 PM
127.0.0.1 - GET /realms/files/%2Fdefault2?shouldCreate=true&realmType=reference HTTP/1.1 200 80 - 0.702 ms
http3:05:06 PM
127.0.0.1 - GET /realms/files/%2Fdefault2%2F__partial%2F4655d29713f9783f6812dcd19cb433dc%2F746aac7bde8129cfc5f046114616e28aa474f33d?shouldCreate=true&realmType=partial HTTP/1.1 200 162 - 0.704 ms
http3:05:06 PM
100.96.7.122 - POST /auth HTTP/1.1 200 1046 - 8.091 ms
http3:05:06 PM
Proxy upgrade: [1439] new connection from 100.96.7.122:58682
3:05:06 PM
The Realm Object Server proxy has 4 open connections to the sync server
3:05:06 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:21,“unknown”:4,“total”:73}
3:05:11 PM
127.0.0.1 - GET /health?thisInstance=true HTTP/1.1 200 20 - 0.665 ms
http3:05:18 PM
100.96.2.59 - GET /health HTTP/1.1 200 20 - 2.482 ms
http3:05:18 PM
100.96.23.155 - POST /auth HTTP/1.1 200 794 - 2.416 ms
http3:05:18 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:20,“unknown”:4,“total”:72}
3:05:21 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:21,“unknown”:4,“total”:73}
3:05:41 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:20,“unknown”:4,“total”:72}
3:05:51 PM
WebSocket closed, removing the listener
log3:06:08 PM
WebSocket client connected, adding a listener
log3:06:08 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:21,“unknown”:4,“total”:73}
3:06:11 PM
127.0.0.1 - GET /health?thisInstance=true HTTP/1.1 200 20 - 0.510 ms
http3:06:18 PM
100.96.7.122 - GET /health HTTP/1.1 200 20 - 2.483 ms
http3:06:18 PM
100.96.7.122 - POST /auth HTTP/1.1 200 794 - 2.484 ms
http3:06:18 PM
Open files in Realm Object Server: {“regular”:29,“directory”:0,“character-device”:1,“block-device”:0,“pipe”:18,“symbolic-link”:0,“socket”:20,“unknown”:4,“total”:72}


#5

@chronofar Can you share the logs on the client side as well? Are you wiping the simulator in between switching from partial to full? There is underlying state that needs to be cleared - have you tried using an admin user ?


#6

@ianward below is the exception that is thrown if I try and do something with the User object while it’s invalid:

08-18 18:16:44.757 30239-30239/chronofar.manageme E/AndroidRuntime: FATAL EXCEPTION: main
Process: chronofar.manageme, PID: 30239
java.lang.IllegalStateException: Object is no longer managed by Realm. Has it been deleted?
at io.realm.internal.InvalidRow.getStubException(InvalidRow.java:188)
at io.realm.internal.InvalidRow.getModelList(InvalidRow.java:109)
at io.realm.chronofar_manageme_data_realm_UserRealmProxy.realmGet$transactions(chronofar_manageme_data_realm_UserRealmProxy.java:232)
at chronofar.manageme.data.realm.User.getTransactions(User.java:77)
at chronofar.manageme.data.realm.RealmController.getTransactions(RealmController.kt:197)
at chronofar.manageme.viewmodels.TransactionModel.getAllRecords(TransactionModel.kt:106)
at chronofar.manageme.viewmodels.TransactionModel.getValuesForAddMoneyFields(TransactionModel.kt:140)
at chronofar.manageme.fragments.AddMoneyDialog.onCreateDialog(AddMoneyDialog.kt:99)
at android.support.v4.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:328)
at android.support.v4.app.Fragment.performGetLayoutInflater(Fragment.java:1226)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Beyond that I don’t see a lot of logs. If I follow along in the debugger I can see the call to the change listener which on Full sync gives me a valid user proxy but on partial is still invalid.

I’m not wiping every time I’m switching, however I did a test with this now. I wiped, did partial sync, and get the above error when I try to use the User object. I wiped again, did full sync, and at first the object is invalid, but once the full sync completes the object is valid and usable.


#7

@chronofar it appears that whatever object you are using is becoming invalid or going out of scope for some reason. Are you using multi-threading?


#8

@ianward yeah that’s what I thought from the error as well, however turning on fullsynchronization and changing absolutely nothing else returns a valid proxy, so it doesn’t seem like that’s quite my issue here. Also note the object is never valid. It starts as invalid (b/c the async query hasn’t loaded yet), and then when the change listener is called it’s still invalid (and if I try to use it I get this error). Basically it seems like realm never manages to pull down the query on partial sync, thus the object never becomes valid, where on full sync eventually once it gets cached it’s valid.

I’m not using any multi-threading in this case, this is all done from the UI thread.