realm / realm-object-server

Tracking of issues related to the Realm Object Server and other general issues not related to the specific SDK's
https://realm.io
293 stars 42 forks source link

ROS only syncs once for read-only realms #30

Closed nickharbin closed 7 years ago

nickharbin commented 7 years ago

I have ROS installed on a remote CentOS machine. I am accessing it using an iOS application I am developing.

I have created a realm in the common area (/realmName) with the server admin and the __admin realm shows nil for the owner of that realm.

I created a second user that is not a server admin and created a realm for that user (/~/realmName).

When I log in as the second user, the notification block is called in my iOS application only once. Any changes made during this time are not reflected in the Realm Browser pointed at the user's realm and no changes made to the common realm are reflected in the iOS app. If I close and reopen the iOS app, all pending changes are synced in both directions and everything is up to date, but again no new changes are reflected.

If I make the second user a server admin and then start the app everything works as expected. I can even close the app and revoke admin on the second user and it all still works.

Also, user's authenticating with google have the same problem, and I am not able to make those users admin so the problem persists on all app launches.

I have a MacOS ROS installed on my home network as well and the above scenario does not occur. On the MacOS server all the data is synced immediately just as expected.

Let me know if there are any logs or anything else I can provide that can help. I am unsure if this issue is caused by a configuration problem on my end or if it is an issue with ROS itself.

teotwaki commented 7 years ago

Hi @nickharbin,

Could you provide the server logs, when you reproduce this issue? In addition, could you clarify which version of CentOS you are using? 6 or 7? Thanks

bigfish24 commented 7 years ago

Just a note, creating Realms with an admin user doesn't register them in the __admin Realm currently. I don't think that is causing the issue but wanted to point out.

nickharbin commented 7 years ago

Hi @teotwaki,

I blew away the entire installation and started from scratch with logging set to 'all' and that log is attached. When I originally posted this issue yesterday I was using a CentOS 6 install in OpenVZ. I rebuilt the install with CentOS 7 to see if that made a difference. It did not.

The attached logs are from the CentOS 7 install. The only activity is starting the server and then running through the scenario outlined in my initial post.

The attached log is from /var/log/realm-object-server.log. Let me know if there is anything else you would need.

realm-object-server.txt

radu-tutueanu commented 7 years ago

Hello @nickharbin,

There are multiple things happening in the logs, but I noticed the following: The admin token is the one ending in '...Of/aexc94pJDfuBMOuLo7S8fBm+w=='. Some of the connections open 2 sessions, one for their own path "/~/realmName" and a second one for "/rundlc". Only that the token used to access "/rundlc" is not the admin token(line 57 in the logs). Could you please share the code used to create the two realms?

Thank you!

nickharbin commented 7 years ago

Hi @radu-tutueanu ,

I am creating the /rundlc realm by signing in to my app as the server admin, using the username and password I created when installing the ROS, the first time I run the app. This also creates the /~/realmName for the admin user (all code is posted below)

I then delete the app and rerun it signing in as a standard user. The same code runs where the standard user connects to the /rundlc realm and also connects to, and thus creates, his own /~/realmName file.

All connections should open two sessions, one to /rundlc and one to /~/realmName, except for when the Realm Object Browser is the one connecting. I connect with that to test whether changes made are making it down to the iOS client.

This code creates/accesses the realm files: Note: the RealmManager.shared.user is the SyncUser from when the user authenticated or the user existing at SyncUser.all().first (which has only ever contained one user)

   func defaultRealm(with notificationBlock: @escaping NotificationBlock) -> (realm: Realm, token: NotificationToken)
    {
       // baseConnectionURL() points to /rundlc
        let config = Realm.Configuration(syncConfiguration: (RealmManager.shared.user!, Settings.baseConnectionURL()), objectTypes: [Song.self, Score.self])

        let realm = try! Realm(configuration: config)

        let token = realm.addNotificationBlock(notificationBlock)

        return (realm: realm, token: token)
    }

    func userRealm(with notificationBlock: @escaping NotificationBlock) -> (realm: Realm, token: NotificationToken)
    {
        // userConnectionURL() points to /~/realmName
        let config = Realm.Configuration(syncConfiguration: (RealmManager.shared.user!, Settings.userConnectionURL()), objectTypes: [Song.self, Score.self])

        let realm = try! Realm(configuration: config)

        let token = realm.addNotificationBlock(notificationBlock)

        return (realm: realm, token: token)
    }

This code runs in the viewDidLoad method of the view controller presented after a successful login.

Thanks for looking into this for me and let me know if you need anything else.

nickharbin commented 7 years ago

I did some tests over this weekend and I was able to reproduce this behavior with the iOS demo app included in the macOS download.

I modified the demo app to point to my centOS 7 install of the ROS and then changed the line below:

static let syncServerURL = NSURL(string: "realm://\(syncHost):9080/\(syncRealmPath)")

Notice I changed the demo app to point to a realm file in / instead of /~/.

I then started the app and logged in as my server admin and created a couple tasks.

I deleted the app and reinstalled, this time signing in as a standard user. The same behavior outlined above occurred. Changes to the realm were only communicated when the app was first opened and then the connection was closed. Once I made the standard user a server admin the app behaved as intended.

I thought I'd let you know since this is a much easier way to reproduce this issue. Let me know if you need any more information.

radu-tutueanu commented 7 years ago

Thank you a lot for taking the trouble to reproduce this using the RealmTasks app. There is indeed a bug into how read-only realms( in / for regular users) sync. We will be working on fixing it.

teotwaki commented 7 years ago

@nickharbin,

Could you confirm that the latest version of the SDK doesn't have this issue anymore?

Thanks

teotwaki commented 7 years ago

Closing due to inactivity.

ianbradbury-bizzibody commented 7 years ago

Please can this item be re-opened.

I am experiencing this issue.

I had previously been experiencing this issue on a platform that had been through several upgrades. Seeing as I was only "playing" I thought I'd burn the server and start over.

What I did not expect was the same behaviour after installing everything from scratch using the new v1 release (Ubuntu 16 / Swift 2.3.0 / Server 1.0.0).

The behaviour is that data is synced on first connection to the ROS - but no further syncs occur. Only restarting the app causes another - and only 1 - sync.

I have attached a segment of log from just before to just after the issue occurring. ROS Log ros.domain.com.txt

bigfish24 commented 7 years ago

Apologies for the confusion! The underlying issue is that we do not support "read-only" Realms yet and we need to make this explicit in the documentation.

The reason on why this is limited today, is that by default, when you open a Realm in the client SDK for the first time, it creates the Realm file locally, writing the schema to it. The writing of the schema is an operation that is then synced when the connection to the server is established. The problem though is that the server is assuming the client is read-only so it breaks the connections because incoming writes are not allowed.

To work around this for now, you should just use read/write permissions.

There is a more obscure way to work around it by opening a Realm in "dynamic" mode which skips writing the schema, but it is a private API. In addition, when using a dynamic Realm, you have to use string-based methods versus the type-safe ones. We use this in the Realm Browser, but have not promoted it publicly.

ianbradbury-bizzibody commented 7 years ago

Thanks @bigfish24 - this is important information and is going to throw a spanner at my project. But I appreciate this is really early days so I blame myself for not realising sooner.

I've looked in the issues list for a T:Feature that I can follow to keep an eye on this. But I can't see one. Can one be added?

Of course I'm going to have to ask..... when? But I'll wait to ask in the right place. ;)

bigfish24 commented 7 years ago

@ianbradbury-bizzibody I am truly sorry this is coming up now. I can't commit to a timeline right now, but will hopefully be able to have more details later in the week/early next week. We know this is a major issue and we will be fixing it. What is your timeline on when you need it fixed?

ianbradbury-bizzibody commented 7 years ago

Fortunately it's just a hobby project. I figure I can continue working away and not worry about his for a while. If it could be delivered some time in the next 3 months that would be really really great. (But I recognise the pressure you are all under)

bigfish24 commented 7 years ago

@ianbradbury-bizzibody I think that is a pretty reasonable assumption, definitely is a requested feature since dev teams want to control errant write access, even in just development.

jpsim commented 7 years ago

This has been fixed in realm/realm-cocoa#4910.

Note that if a sync user ever has the possibility of only having read access to a Realm, the only safe way to access that Realm is through the asyncOpen API. This is because the synchronous API provides access to the Realm immediately (yay offline-first!), which eagerly writes some metadata information to the Realm (e.g. schema), which then fails if the server rejects the changes due to insufficient permissions.