Sync architecture questions - docs just don't cut it


(Chev) #1

Docs really need an update. Besides the super-trivial examples, there are no architecture examples for real-world apps using the best practices suggested. Docs are incredibly frustrating littered with:

Query-based Sync is not recommended. For applications using Realm Sync, we recommend Full Sync. Learn more about our plans for the future of Realm Sync here.

Yet the majority of examples demo query-based sync.

Docs continuously tout Offline-First yet all sync examples require logging in to the cloud first.

Docs recommend using Full Sync:

For example, a common pattern is to use a global Realm for shared data at a base path /globalRealm and put user-specific data in an individual Realm at each user's scoped path: /~/myRealm

Yet don’t see any examples on implementation of this.

Really is frustrating trying to follow these suggestions without further elaboration.

From what I am able to gather:

  1. Common shared data that needs to sync to all users should share a common realm like globalRealm and sync to all users
  2. User-specific data should live in their own realms: /~/myRealm which only syncs to the relevant user.

If we take the car example in the docs, we saying the Car schema should exist in the global realm so that models like ford and honda sync to all users. This car data is also needed in the user’s specific realm though as User.cars schema links to Car schema. So how is global car data kept in sync with the car data in the user’s realm? I assume this requires a sync from globalRealm to the users realm?

If we suggesting Offline-First then I assume we using realm database first and syncing only when we oline - but where is the example of that flow? All examples require cloud login first and not clear how the local realm database integrates?

Seems like a decent product and I have elementary sync working between cloud, react native and node apps - but the real-work architecture suggested is elusive.


#2

Previously the recommendation was for everybody to use query based sync. Hmm… I assume this was changed after the MongoDB acquisition. It would be really nice if we as developers get notified about these things?


#3

According to the roadmap, it looks like query-based sync will be rebuilt in the second half of 2020.

Edit: to answer your question about realm being “offline” and online. The first time you open a synced realm, device must be online. The data will sync and in the future you can open the realm synchronously when the device is offline. https://docs.realm.io/sync/using-synced-realms/setting-up-your-realms#how-to-open-a-realm

As far as your database architecture, you can absolutely open two realms with shared schema. You can then copy objects from one realm to another, see https://stackoverflow.com/questions/35110065/copy-all-objects-from-one-realm-to-another


(jay) #4

@harrynetzer Awesome answer!

See the Configure A Realm documentation noting how the Realm configurations enable you to change which Realm file realm is talking to.

You can have multiple configuration objects, so you can control the version, schema and location of each Realm independently.

Also, note if using multiple realms, Realm calls should be encapsulated in autorelease pools or within a function so the app can deallocate references. See Passing Across Threads for a code sample.

Lastly, shared schema? I don’t think that’s an option - each Realm has it’s own discreet Schema and they cannot be linked. However, you can use the primary key as an external key to associate data between realms. Also, queries across realms is not possible currently.


To the OP

From what I am able to gather:

Common shared data that needs to sync to all users should share a common realm like globalRealm and sync to all users
User-specific data should live in their own realms: /~/myRealm which only syncs to the relevant user.

These are valid points but, it all depends on your use case. For example, suppose you keep track of the State a users lives in - that would be user specific and in your question would live in it’s own realm. What if though - you want a list of all users who live in Texas? That complicates the query.

I would suggest starting development in one Realm for all data. As your queries and needs become more defined you can then split out data into separate realms if needed. We are working with thousands of objects, many users and are not finding we need to break any data out as of yet.

This car data is also needed in the user’s specific realm though as User.cars schema links to Car schema. So how is global car data kept in sync with the car data in the user’s realm?

It’s not. Use a single Realm for that use case.

If we suggesting Offline-First then I assume we using realm database first and syncing only when we oline - but where is the example of that flow? All examples require cloud login first and not clear how the local realm database integrates?

The integration is somewhat auto-magic and pretty transparent - as you write data to Realm, it persists locally and sync’s with Realm Cloud in the background.

Here’a link to a question that I answered a while back that demonstrates how to authenticate. Once that’s done, any further reading/writing to realm, as I mentioned, persists locally and sync’s the Realm Cloud in the background.


(Nikola Irinchev) #5

Just want to clarify that you can definitely open as many realms as you want (subject to file descriptor limits, which on iOS is very low - it maxes out at around 10-12 synchronized/~20 non-synchronized Realms last I checked). The try! Realm() is just a shorthand for creating a Realm with the default configuration. But you can most certainly do:

let realm1 = try! Realm(configuration: config1)
let realm2 = try! Realm(configuration: config2)

These can be open at the same time and you can query/write to them independently of one another. They can definitely be initialized with the same schema, but they cannot share objects/queries/writes as you mentioned.


(jay) #6

@nirinchev That is really good information. Been using Realm for years and didn’t know that was an option - updated my answer above to match.

I cranked out a small test app and it works perfectly and can read/write to multiple Realms at the same time. The only gotcha is if you have Realm Objects defined outside the class, all Realms have the same schema as the models are instantiated as soon as you connect to a Realm. If the Realm Object Model is moved inside the class, there’s an error:

RLMObject subclasses cannot be nested within other declarations. Please move …TestClass to global scope.

Do you have a suggestion on when/how to define the Models so the Realms have different Schema?

This has gotten off topic from the original question/observation about the docs so apologies.


(Nikola Irinchev) #7

Seems like in Swift, you’d need to set the objectTypes property on the configuration.