This talk introduces the open-source Realm Database and shows how Realm Platforms completes it with server-side components. Together, this allows you to treat synchronization and network as an implementation detail of your technology stack. Features like live collaboration, which would have been a major undertaking, become easily available to every developer. This talk shows you how you can build apps in a reactive manner on top of a database which takes care of the rest.
I’m Marius Rackwitz, and my presentation is about crafting collaborative apps with Realm.
A collaborative app is an app which can be used by multiple people at the same time to work on the same task. There are many collaborative apps out there and I’m sure you’ve used them in your lives before.
Realm Database (1:18)
The Realm Database was the first product we launched.
What is Realm and what isn’t Realm?
Realm is not an object relational mapper. It is the database itself. In fact, it is an embedded, NoSQL, object-oriented database. For us, embedded means it was optimized for the hardware constraints of mobile, unlike SQL Live which was originally built for guided missile destroyers to guide rockets. We have built Realm from the very beginning with mobile in mind.
NoSQL means a differentiation from many new databases, especially on the sever side. It’s not a database which has a big schema and is constraining the type of data you can put into it. Realm has a fixed schema to allow this performance and be as fast as it is.
How does being object-oriented work for Realm?
A schema definition is only done in the code; it’s not done in something you have to mess around with if you’re working on a bigger team and need to merge conflicts you don’t really understand.
You can just define a new class in the code as you do any other class. You have to inherit from a framework-given special superclass, which is just called
Object in the case of Realm Swift, and then you can define your properties.
Get more development news like this
There are some rules around that, but for atomic properties it’s relatively straightforward; you can define it as dynamic properties so that they become available to the Objective-C runtime. You can also define links even with our built in correction type,
List, which allows an object to have children with a new schema. There is no need to introduce any foreign keys. There is no object relational mismatch; you can describe just like how it is.
Realm Platform (5:00)
Let’s move on to the Realm Platform which we just introduced at the end of last year. We extend the mobile database to the server side. This gives new deployment opportunities.
So far, the mobile database has only been on iOS and Android in the respective native host languages, which are Java for Android and Objective-C and Swift for iOS development. However, we also support a cross-platform approach with technologies like React Native.
On the server side, you can deploy the database yourself on existing infrastructure or in the cloud of your choice. You can integrate with event handling, with the new GS framework, which allows you to access the object and interact with events and make writes.
What can we achieve with that? What does this platform allow you to cover and how would it work work?
In the most simple scenario, you could give your users an easy way to synchronize continuously and back up their devices to your server. That way, if they lose their devices or switch to a new one, they can just sign up or login to the app again and get the old data. That can be a standard, but it gets a bit tricky with existing technologies if you want to allow cross-device synchronization.
For example, I could sit at home on my iPad on the couch and set up my grocery list for tomorrow when I’m going to the grocery store. I could write down what I want to buy and my grocery list will be automatically synced into the cloud on my server. Then, when I’m at the store tomorrow, I just can cross off what I put in my basket, and we’ll see later on if I forgot anything.
With that, we can go to a more complicated example. We could allow multiple people to interact with the same data simultaneously. That is the use case that this talk is about, real-time collaboration.
Real Time Drawing Example
For our launch, we built an example application which allows you to draw together on a virtual canvas. This app is actually quite handy for me trying to learn Japanese, because I can use it together with my sensei, my teacher, to practice the stroke order for kanjis and radicals. We could use that app and FaceTime at the same time, using the picture-in-a-picture mode, and he could instruct me which kanjis to write or just show me drawings.
For example, he could be introducing me to the kanji for “clear up.” In fact, I can learn this based on radicals I already know. As soon as I draw something, all my brush strokes will be created as objects in the canvas application and will be synced up to the server and made available. In the other user’s app, they will be automatically downloaded to my sensei’s iPad so they can be shown there, and he can give me some feedback. He can then draw on his own device to show me the rest and integrate that into a larger context. All his changes will be synchronized in the same way. At the same time, I can still do my changes and they will also be synchronized over.
In the case there are conflicts, the Realm Platform will take care of resolving those conflicts and integrating everything into one consistent history. This gives you consistent data across the devices. My changes are getting synced over, but now he could even lose his connection.
Because the Realm Platform is built on the Realm Database which supports persistency, it supports offline first. A device can be offline and it’s not a big deal. In fact, we don’t even need to take care of this scenario within our example app in a bigger way, so my teacher can just keep drawing and I can keep drawing. My change will still be synced up to the server. His change will just stay local. Once he’s back online, he will get the new changes I did in the meantime, and his change will be synchronized over.
If you step back to our use cases, we can now not only use a single round as we did in this example, but instead use multiple rounds which are synchronized separately with individual permissions: some of them available to just myself, others available as shared. We can effectively ban JSON from our apps.
We can also eliminate the object-relational mismatch we have to deal with, which is good because dealing with JSON, especially from a type safe language like Swift, gets incredibly tricky to do correctly. Just look at the sheer number of frameworks in Swift to manage that. Do we really to reinvent the wheel over and over again? You don’t need to spend your precious time writing code to map JSON back and forth. That reduces even the effort across multiple platforms because you would need to solve it on every single platform if you are targeting iOS and Android.
How is that possible on the server side? Realm offers built-in notifications.
The most fine grained way is notifications on individual properties. These are available via KVO. We integrated very closely with the Objective-C runtime, which allows you to get changes whenever one particular property of an object changes and triggers data changes from there in a very reactive manor.
You can also do that a little bit more on objects. Going even further, we also allow fine grained updates on collections, which allows you to tie that directly to your table views and collection views and allows you to show nice animations when objects are locally added or even from other devices interacting, because you know what’s in your tables, but each data changes.
Going even further, you can trigger behavior in a global way if you set up notifications on the whole file, and with the Realm Platform we will learn about notifications you can trigger on all Realms which are synchronized to the server.
So how does that work and how does that fit together for our larger topic of replacing our backends?
Event Handling (15:00)
If you have an app for coupons, we could create a coupon object in a Realm which is synchronized to the server for a particular user. In the object we set a coupon code for the given code the user has entered or scanned the QR code. This object will be synchronized up to the server and it will trigger a notification, via the global event listener, which is part of the event handling framework we offer.
You can trigger your validation code which even allows you to make direct modifications to this object. So if you figure out that this code is valid for the purpose the user is using it for, then you can just set an
isValid property of the coupon object to
true and this change will be synced back to the server side and will be synced back to the client and made available there.
Say you have set up a listener on the
isValid property. You can show in the UI that the coupon is valid and the user can continue. So far, so good, but if you think about it a little bit further, we have multiple Realms involved, how does that all work?
Managing Access (16:35)
How do we manage access to Realms? Maybe you would think with a REST API, but we don’t have to deal with JSON anymore. We use Realms for managing access as well. We fully commit to our own approach here. To make this possible, we have some special Realms.
One Realm you would not directly interact with is the Admin Realm, which is global to the world server we use. It’s a synchronization engine for building the server itself. That is the single source of truth for all permissions and Realm files and users on the server.
Beyond that, you have user specific Realms. There is the Management Realm and the Permission Realm.
The Management Realm is responsible for making modifications to permissions. You can create the permission change objects, and permission offer response objects. You will learn about the former in the next step.
The Permission Realm allows you to mirror permissions affecting the particular user. The path for this Realm would include a user ID. That would be the concrete permission Realm for this user and you would see in that Realm all permissions which are affecting this user, which are all permissions he has granted to others and permissions which were granted to him from others.
Putting It Together (18:40)
If we put this all together, we can see how you can make permission chains.
In our first step, we would communicate with the Permission Change Realm: user IDs, from one user to the other user, effectively making the permission change. This could happen over existing channels like LINE, Facebook Messenger, Snapchat, etc. Then we set up the permission change object, which encodes the user ID and which path we want to set rights for on the server.
This is then added to the Management Realm and will be processed as soon as it is synced up to the server by the event handling framework. This, if done right, will trigger a change to the Admin Realm which stores, as we have learned, all the permissions. This change, internally, will cause this permission to be reflected within a Permission Realm of the user we have received the user ID of.
If there is an error, a notification pops up for this permission Realm and you can directly interact with that and react to the new permissions which were granted.
We have plans for supporting a mobile platform over server-side languages as well. We have a repo on GitHub where we collect issues around that; feel free to post any wishes so that we can make plans. I’m not aware of any concrete plans for PHP, but we definitely have plans for supporting more server-side languages.
About the content
This talk was delivered live in March 2017 at try! Swift Tokyo. The video was recorded, produced, and transcribed by Realm, and is published here with the permission of the conference organizers.