World tour eric maxwell header

Realm World Tour 2017: The Realm Platform Experience

Introduction

I’m Eric, I’m a Product Engineer at Realm. Today I will talk about the Realm Platform, which is a real time syncing service that works on top of a product that we’ve had for a few years now called the Realm Database.

We’re going around different cities, both in North America, Europe, and Asia, and sharing how to use the platform and how to get started.

How many people are using Realm in their day to day development? 25-30%. And for those of you who aren’t, you’re probably using an app that’s been built on Realm. The database has been out since 2014. And some of the biggest companies are using Realm.

Realm is different than your traditional mobile database. If you think of Core Data or SQLite, there’s differences when it comes to Realm. First, it’s a fully object database. We’re not an ORM, object-relational mapping tool sitting on top of SQLite. We are a complete replacement for the SQLite database and Core Data. There’s a couple other differences we take on database development, too. When you run a query and you pull data back, everything’s loaded lazily, and everything’s live. Once you run a query once, you never have stale data. You always have the most up to date data in your query. We also have the idea of a reactive programming model, where you can attach notification blocks to the queries. If anything changes with those results, you’re automatically updated and you can update your UI.

Reactive Mobile Database with Live Objects

There’s a four pillar concept to working with Realm, and we’ll touch on each part of this:

Objects

First of all, with Realm, you’re working with objects. We are not a schemaless database. With Firebase you’re storing JSON up in the cloud, but we’re storing actual objects.

Our platform and database is cross-platform: we support Java on Android, Swift, Objective C, JavaScript with React Native, and even Xamarin. This presentation focuses mostly on Swift and Java, and some JavaScript.

In Realm you define these classes that are modeling data that you’re storing in your database.

class Dog: Object {
  dynamic var age: Int = 0
  dynamic var owner: Person?
}

In Swift we have a Dog class, which is a persistent object, and you can add any properties you need on these. In this case, it has an age, which is an integer, and the owner of the dog, which happens to be a person, which is another Realm object.

public class Dog extends RealmObject {
  private int age;
  private Person owner;
}

In Java it’s a similar syntax. Once you define all of your objects, and you have this schema defined, creating the class and running your application is enough for Realm to go and create this schema database.

Queries

And then, as you’re building your application, you’ll start to run queries to populate your user interface.

let puppies = realm
  .objects(Dog.self)
  .filter("age < 2")

In Swift, here we’re getting a list of dogs, and we’re filtering by their age less than two, and we’re going to call that list puppies any time we access the objects in that list. It’s always going to be exactly what’s in the data at that moment in time. If you run this query once, and you look at the data after maybe you’ve changed the data in the background thread somewhere, it’s always going to pull back the latest data.

Realm is lazy. We’re not pulling all the data back, we’re running the query, pulling a reference to that, so that when you go to fetch the actual property that you need, it’s then going to disk and pulling that property out. That helps us be more efficient.

RealmResults<Dog> puppies = realm
  .where(Dog.class)
  .lessThan("age", 2)
  .findAll();

Java, it’s similar. It’s a different syntax. Whereas we have a NSPredicate-like syntax in Swift, with Java, it’s what we call a builder syntax, where we’re building up this query.

Notifications

After you write queries, and you initially set up your user interface, at some point, you might have, maybe a background thread that’s going fetching some JSON data, putting it into your database, and then you want to update your user interface.

You don’t have to requery because the queries are live, but it’s nice to have something to tell you that the data’s changed in that query, and give you the chance to execute some code to respond to that.

We have this notion of change listeners, or notification blocks, and depending on your language it’s written differently.

let token = puppies.addNotificationBlock { changes in 
  self.updateUI(with: changes)
}
puppies.addChangeListener(new
RealmChangeListener<RealmResults<Dog>>() {
  @Override
  public void onChange(RealmResults<Dog> puppies) {
    updateUI(puppies);
  }
});

In the Swift example, we’re attaching a block of code to run whenever one of our queries changes, and then we can update our user interface based on those changes.

When I add this notification block to puppies, it’s not going to fire if somebody inserts a new dog. It’s not firing when something changes with the dog database, it’s firing when something changes with that puppy’s query. It would have to be a new dog added, maybe, where their age was less than two, or a property on one of those results changed, or the object was deleted.

Transactions

And finally, once you’re in a zone where you’re updating your UI, then at some point, you’re going to want to write data back, and to do that, we use transactions, and we require you to run all of your updates and transactions because Realm is a fully ACID-compliant database, and this helps ensure that your database is always in a consistent state.

try realm.write {
  dog.owner = Person(name: "me")
}
realm.executeTransaction(new Realm.Transaction() {
  @Override
  public void execute(Realm r) {
    Person me = new Person("me");
    r.copyToRealm(me)
    dog.setOwner(me);
  }
});

The syntax is more succinct in Swift than it is Java, with its anonymous inner classes. In the Swift example, you say realm.write, everything you put in this block is going to be run within a transaction, after you’ve set all your properties, created your objects, as long as there were no errors. As soon as it exits the block, it’ll push those into the database, and then anybody else who were listening to query notification changes would automatically be notified if it affects their query.

Q: If this is an ACID process, for Swift, where’s the roll back, stuff like this? Eric: There’s two ways to run transactions. In this case, if you’re doing it with this block syntax, if there is an error, Realm will roll that back for you. There are ways to explicitly begin, commit, or cancel the transaction yourself, if that makes more sense. Then you could have your own custom logic. This way is going to commit it, as long as there were no errors. If there were an error, then it would auto cancel it for you.

Q: Would it do this asynchronously? Eric: Yes. We have methods to do things asynchronously, these examples are not asynchronous, but when we get to the actual code, I’ll show you asynchronous examples.

Those are the basic concepts of working with the Realm Database.

Seamless Data Sync for Realtime Apps and Collaborative Features

The database has been out for a couple of years but we recently launched a new data synchronization service. You could think of as competing with CloudKit - when you’re online and connected, Realm seamlessly synchronizes your local database to an object server, what we call the Realm Object Server, living in a cloud that you can host wherever you want

Get more development news like this

Once it gets up to the cloud, that object server will automatically synchronize it across all your different clients (could be on iPhones, Android phones, tablets, any device that runs the platforms we support). It will automatically keep it all in sync for you. As a developer, you’re still working at the database level, but all that network synchronization and passing data is happening for you. It also works seamlessly offline.

Q: On the backend, can you synchronize it with other databases? Eric: You can with the Professional Edition. Because the Realm Object Server runs as a Node.js app on the backend, we have hooks to hook into the database, even listen for data coming in that you care about. You can pull that data out with a small JavaScript app, and plug it into whatever you need to in your backend, which could be a database, you could make RESTful call, plop it on a queue somewhere. And we have, also, connectors to take data from your existing databases, and plug that into the object server, and then have that synchronize down to devices.

Q: Is the object server open source as one? Eric: The object server is not open source. The core database is open source, it’s written in C++. It’s the same C++ database code that’s running on platform. We call in, we have this core, what we call the core C++ database, and the object layer on top of that, and then we have bindings for all the platforms we support. As a developer, you don’t need to worry about all of that, but if you’re curious, all of that stack is open source, just not the server side.

Q: You mentioned that it’s Java on Android, does it support the desktop Java? Eric: It does not. Right now we’re tied specifically to Android. It has to do with the looper threads in Android, so that we have a runtime loop to make sure that all our queries are up to date. It’s something we’re looking to support. But we support MacOS and iOS, so you can write a Mac app with Realm. We also have support for JavaScript, and we have a product called a Realm Studio, which allows you to manage and administer your Realms.

Realm Platform

Realm Platform is nice for developers in your typical app setting where you want to do realtime syncing. I like to use this graphic, that’s how I think in terms of my design:

If I wasn’t using Realm, I’d launch the app, I’ll want to pull down some users, so I’ll make a RESTful request to get some users. It’ll pass me JSON down, which I’ll translate into objects and then save that to disk, using Core Data or SQLite.

That would be fine, but when I go to start implementing it, there’s all these other things that I have to start concerning myself with: Am I online or not? If I build up a bunch of transactions I want to push to my cloud service, am I able to handle that? When I pull data down, can I cache it out of the box so that it’s available for me if I need to work offline? What if the server times out, returns a 500? What if the server released a new edition, and there’s a mismatch between your teams and agreement on JSON?

You can easily encounter situations where you have client apps running on users’ devices that are expecting specific JSON coming down or XML coming down, and your server’s sitting at a different version. There’s a lot of things that you have to get right to make that happen.

With Realm, you’re working at the Realm Database level, and if you’ve enabled the Realm Platform, with the object server in the cloud, it’s taking care of all that communication for you. Not only communication going up, but whenever you’re connected we maintain a socket connection to your server. If the server needs to push changes (which it does frequently any time your clients are saving data) that data goes up. The server notifies all your other clients of that data change. It updates their local Realms, and that comes down immediately without having to implement push notifications or some other service on your own.

With the Realm Platform, we don’t have to worry about all of that data connectivity and translation and marshaling and unmarshalling from JSON. We want you to be able to write a database app and just concern yourself with the client code, and let Realm handle synchronization back and forth with the server.

Once it gets into your server, we have ways to listen to data coming into the object server, and hook it into your backend. We also have ways to listen to interesting data, e.g. a Postgres database on your backend, and feed the Realm Object Server, and let that handle the broadcasting.

The data access API, that you can run on your server, runs as a Node.js app:

var Realm = require('realm');

var results = realm.objects("Dog");

realm.write(function() {
  results[0].owner = me
})

This is a real simple example, for example we’re not showing getting the connection to the database, but the basics of it is: you require Realm, and then you can work with it, as if you were on the client. You can fetch dogs. You can also listen for events. And you can write within a transaction changes to that data, and then have that be synced out.

RealmPop Demo

I’m going to talk about a game that we wrote specifically for the Realm World Tour. It was written by myself and one of our other engineers named Marin Todorov. It’s a game where two players can challenge each other, and we have Android and iOS versions. The iOS is all Swift. And once they challenge each other, then they’re brought into this board, and they’ll each have their own set of bubbles to pop, all with the same numbers, but the numbers will be in different positions on both of their phones, and it’s random every time. They have to pop the numbers, from the largest number to the smallest.

In that first example, you’d have to pop 46, 35, 14, 7, 2. And if you pop them out of order, you lose. If you don’t pop them first, you lose. The winner reports a score, and that’s where I have a Node.js app listening for those scores coming in, drops it to a file, and then Marin wrote a little Mac app that reports on those.

I’m going to start with some of the Android pieces, and I’m going to jump quickly into the Swift pieces. We’ll see how the APIs are similar calls on both platforms. Then we’ll play the game. At the end, we have these games built for the iPhone and Android. I’ll give you a link and a QR code at the end of tonight, we can all download it and start playing it against each other.

When we start up our app, on both sides, it’s going to come into a splash screen. The first thing we’ll need to do when we connect to our object server is connect with a username and password, so that it knows that we’re an authenticated user that can access this data, since it’s hosted in the cloud.

It will show a loading screen. Then we have a screen where you can put in your name. Every person that downloads and has the app on their phone, they can type in a name for themselves, and that gives them a handle for people who want to challenge them. After they put in their name and hit enter, they’ll go to a game room, which will be a table view in Swift, and a recycler view in Android.

Finally, once somebody if you tap on somebody and you challenge them, they’ll get an alert that says, “Do you want to accept?” If they accept it, the game will get created, and both players will move into it.

RealmPop on Android

I have a simulator running a simulated Nexus6P. And at first, it’s going to launch up into that connecting screen, but not go anywhere yet. We’ll have to add the code to make ourselves log in. I do have the server address we’re connecting to.

Realm runs within your own infrastructure. Unlike Cloud Kit or Firebase, we’ve made a decision to let you host it yourself. Because we feel that many large enterprises want to make sure that they’re owning their data, and that it’s within their system. There’s many people in fear of using a Parse and then it goes out of business, and then what do you do. In our case, we let you host it. And we don’t have our own hosted solution yet, but it’s something we’re looking into if you want to do that.

Let me first show you the model we’re working with. I’ve defined my schema. When we look at the Swift side, it’ll look similar, but more Swifty. We’ll have an ID unique to every player running the app. This ID, depending on if you’re on Android or you’re on Swift, I either use user defaults or shared preferences to create an ID the first time the app’s launched. I reuse that ID every time you relaunch the app. The name that you type in will get stored in the name property.

When you’re available in the game room to be challenged, we’ll have an availability flag that we’ll set to true. And when somebody challenges you, to challenge you to a game, they will pull your player object out of the database, and their player object out of the database, and set their player as your challenger. We’ll attach a notification block or in Java, a change listener, and we’ll launch a dialogue to ask them, based on that property change, so we’ll react to that data change.

Finally, if you accept a challenge, a game object will get created, and that object will be set for your local user. When you set that on the challenger, it will synchronize up to the cloud, and then back down to the other client, that you’re starting a game with.

The player object’s the most complex one, and then we have a game object that gets created for each game, which has two sides, player one and two, and the numbers that we’re going to display, and finally, each side is a temporary object we’re persisting. It’s temporary in the sense that it only makes sense for each game.

Each side, each player, will have a side to play. And we’ll reference the player ID that this side’s tied to. The name to display for the player. How many bubbles they have left, if they are successful, and they do pop all the bubbles, what time they finished in, so we can see who the winner is, and if they didn’t pop it in time, or they popped them out of order, they’ll get a fail flag set and we’ll use that in our app to react to that and end the game, too.

We’ll also be running what we call the Realm Object Browser and connect to the same database.

I have a few players in there, I have this running on my iPhone, an Android phone, and a couple simulators.

Let’s do this log in. If we start in our splash activity, the API calls are going to be similar across versions, but the first thing I’m going to do is to connect to our server. We have to authenticate. I’m going to use simple user name and password authentication, but we also support authentication with cloud kit, Google, and Facebook. And if you have your own identity providers, you can hook those in, too, and authenticate to your databases with whatever IDP you need to.

Let’s say we previously launched the app, and they close the app without any log out. We’re going to see if there’s a logged in user on this device, and if so, go ahead and log them out. And then, we’ll perform our log in process. And I’m doing this in onCreate, which for those of you who haven’t yet started trying out Android, it’s similar to your viewDidLoad. In terms of where it happens in the life cycle.

To log in, it’s a two step process. We first have to define some credentials that we’re going to use to log in. And this is where they’re plug-able. We’re using a username and password that I had already set up. It’s the same username and password that I connected to with that Realm Browser, it’s this default at Realm and the password password.

Q: All the players are logged in using the same data? Eric: No, that’s not the only way. For this game, we’re all connecting to the same database. We have a clone of the To Do app, which has user authentication on an individual level. For your To Do things, it makes sense for each user to have their own To Do’s. In this case, we’re logging in to the same database using an app account.

RealmPop in Swift

For Swift, we’ll start on our splash screen. Once we’re logged in, we come into our screen, we’ll enter our name. That’ll show up in our table view here. And when we challenge somebody, they’ll get an alert, they can accept it, and we’ll come into the game screen.

Let’s talk about the app’s connection process. Rather than copying pasting in the code, I’m going to talk through all the points of the code that make this all happen.

When our application finishes loading, we’ll call this connect method that we’ve set up in the Realm connect class.

Authentication

We have this idea of sync credential; we’re going to get a username and password. And we also give you the ability with Realm Platform to register this user when you log in the first time. In this case, I already have the user created. You can’t call this twice, it’ll error out and say, you’ve already registered a user with this user ID. In this case, I’m going to pass false.

Once I have these sync credentials, they’re plug-able. If I check out, you can see that I can integrate with Cloud Kit, Facebook, Google. If you have custom auth, you can certainly do that, too. Then I log into the server with my credentials and the authentication server URL. Where it’s built up of my host, which in this case, I’m using an IP. You can set up your own DNS for that. We also support HTTPS, which is important for a real world app. It doesn’t come out of the box, because you need to set up your certs, and I haven’t done that for today, but you can run that on HTTPS.

We log in, and this is going to go off in the background, log the user in, pass in a user. As long as there were no errors, maybe if the password was wrong, the user would come back nil. And we might want to try again, or maybe we couldn’t connect to the server, when we might want to try again.

As long as we got a user back, then we’ll set up what’s called a configuration for a default configuration for Realm to use. Anywhere in our app, where we want to connect to our Realm database, even locally, we’ll use this configuration.

If we set up the default configuration, we never have to worry about it later. Any time we ask Realm for an instance of itself that we can use to work with the database, it’s automatically going to be connected to the object server.

Next, we dispatch on the main queue our completion block, which is setting that navigation controllers our first view. That gets us from our connection. And we can start typing in the player’s name.

Q: Do you have to be online to log in and then it will work offline? Eric: You can run it locally on your phones, if you’ve deployed the app, and it has to be able to run offline. If you’ve never launched the app before then you’re going to have an issue there with the logging in. Once you’re logged in, and if you’ve launched the app once, and you go offline, spotty reception for a minute, and you’ve already logged in once, you can still operate in an offline mode, it’s when you’re online again, it’ll synchronize that up.

Q: Do you have a concept of like an anonymous user? Start within the app, and then create an account later? Eric: We don’t have a concept of an anonymous user yet, but it’s something we’re considering. Every user, on a Realm, if you’re connected to the object server on the platform, you have to be authenticated. If you used the Realm Database, and you’re not concerned about everything off in the cloud, you want a local database to replace SQLite or Core Data, then you can use it without any authentication.

Pregame Time

What we call our pregame room view controller, it’s where we’re inserting the username. When our view loads, we’re going to get a handle on this game model object, which is going to hold some state for us as we move through. It also has some helpful methods, which will, for example, get our current player from our local Realm database. And in this case, we’ll store a reference to that.

We get an ID that’s unique to this player and this device. We’ve had an extension here to user default so that the first time you call this, it’s going to create a new ID for you to work with in this installation of the app. Otherwise, it’s going to return you back what it had already created.

Using that ID, we’re going to pull that out of our local Realm database, asking for an object of type player, for the primary key, the current ID.

Then we can set the player object, and then if the player hadn’t existed yet, we’ll go ahead and create that player, and then return a player to the user. Regardless of whether or not the user existed before you call this, you’re always going to get the user back because of the way we’ve written the code. And then we’ll set the initial text for the text view to whatever this user’s name is.

Also, we’re set up as a UI text field delegate. Any time the text changes, we’re going to listen to those changes, and as somebody’s typing those characters, we’re going to update our name on our player object in Realm. And we’ll see that synchronized from the app running in the simulator all the way up to the cloud, and then all the way back down to that Realm browser app that I had running.

I’m going to launch this on a simulated iPhone 7 Plus. I’m also going to pull this Realm Browser up. I had previously logged in with this iPhone 7 Plus simulator and started a player with their ID, or their name being i7 sim. If I pull up my browser, I should be able to see that i7 sim here. These are both connected to an object server in the cloud, hosted on Digital Ocean. As long as Wi-Fi’s working out here to connect, I should see that.

Let’s call this Sim7. As soon as I hit enter here, and I go into the next screen, I’m automatically set up as available.

Once you sign in and you hit enter, and you’re in this game room, it immediately sets you as available. If you remember that property. We see it on different clients, running at the same time. When somebody becomes available let’s say I launched it on here. I have the same app on here. I’m connected as IP6, which you see this user. As soon as I log in, you should see that change.

Whenever you’re not online, it does work offline. Once we’re both logged in, I’ll go ahead and show you getting to the game and then come back to the code.

Time to Play!

I can challenge the guy on the simulator here. I tapped him, and now I’m being asked if I want to join a game. And if I accept, this guy accepted the challenge on my simulator, he created a game, he set the game object on both himself, and on the other player. That data synchronized all the way up to the cloud, all the way back to this phone, and this phone reacted to that by going into the game.

If I were to play, I might do 15, 13, 11, 9, 4, 1, 0. I’ll pop out of order, I popped the wrong one – so you win. And immediately a score gets logged in here, and it says who won and what their time is.

Back to the Code

They hit enter, we’ll segue way into the next view, as long as the text field isn’t empty. And that is our game room.

When the game room starts, it gets a handle on this game model. The game model setup is like a singleton. And we’ll store a reference to work with here. We’ll get our current player again. And in this case, we’ll get other players. We’re going to use this to populate our table view. Our view did appear. There’s two things we’re going to do.

First, we’re going to attach notification blocks to both me and we’re going to attach it to other players. When somebody challenges me, they’re going to set themselves as my challenger. I want to be able to respond to that. Whenever my object changes, I have this me object that I pulled out of the database, and I’m saying, any time I change, there’s a new property set, I want to be notified, and then I can interrogate and see what’s different about my object, or what’s set on my object.

In this case, I can see if I have a challenger, I can handle an invite. Pop up an alert and see if my user on this device wants to play a game against the other person. Maybe I challenge somebody else and they created a game and set that game object on both of our players. I’d have a current game set and I might want to show that game view controller and transition into that with this game challenge that’s been created.

Second, if there are any changes to the players, e.g. a new player comes into the game room, leaves the game room, we need to change their availability, or a new player signs in on their phone, then we’ll have a change block fire.

In this case, we’ll write a little method. We can animate any deletions, insertions, or changes to the rows. Once the view will disappear, any time we go out of the game room, we’ll reset ourselves to not available.

Here I am, and the iPhone 6 is available. As I leave and come back in, now it’s working better. Then you can see that that happens right away. When I leave the game room and I go back to entering my player name, I set my availability to false.

Let’s talk about challenging a player.

Q: Every time we change the model, are you wrapping it in a transaction? Eric: Yes, you have to.

Conflict Resolution

To handle conflict resolution, there’s a few simple rules to follow.

When two of the same objects are updated, e.g. you had two objects, we’ll call object one, running on two different iPhone clients or Android, whatever. And both of those clients made an update on their local databases to the same object at roughly the same time, and those get synchronized up. Unless the changes are on the same property, it’s fine, Realm will merge those together.

If object one updated property A and object one on this client updated property B, then when it comes up, A and B will be the merged result of that.

If they updated the same property, we have what we call a strong eventual consistency. The clients on both sides and the object server will agree as to who’s the winner. Any time you do updates, if there is a conflict, the last update wins. If they come in at nearly the same time, but the other client was later, then they’re the one that wins. That data, obviously, would need to get synced, and it happens seamlessly back down to the other client that lost, and then if you’ve got a notification block attached, you can react to that.

For some apps you might need to do some coding. Let’s say you’re doing a word processor app and two clients update the name of that app, or name of your doc. You might need to come back to the other user and say, “This was changed, do you want to accept or overwrite?” But it depends on the situation. For our game, it doesn’t matter in the way in which we’re using it.

You’re never left in an inconsistent state. The rules are always the same, they always work out. If client one updates an object, but then client two deletes that object, deletes always win. And if they’re inserting into a collection of objects, then it’s order of insert.

Q: On the backend, is there any mechanism for implementing? Eric: Not currently, we define those rules, it’s the way the system works. The rules would be on your client side because you would have to decide if you saved a change and when that change is, I don’t want to say reverted. But you’d save a change and then you might get a notification that your object’s changed again and this is the new value. You might have to handle that. But the logic would be on your client side.

Q: It gets a bit more complicated when you have other data systems in play. Eric: Yes. With any realtime syncing, you’re going to have to maybe consider some of those things. We can’t solve all consistency issues, but we can make sure that your data’s not corrupt and there are a reliable set of rules you can always count on. Right now, there’s not. The API, because when you think about it, you’re working with the local database. You don’t even know when that syncing is going to happen. It happens near real time, if you’re online. But if you’re offline, e.g. in a tunnel, it might be. Maybe it’s something we consider in the future.

Q: Along the same lines, is it possible to have simultaneously a Realm that is synchronized and one that is not for local data? Eric: It’s not a use case we’ve run up against, but you can connect, you can break your model out into different schemas. These models are all part of the same schema. But when you build your configuration, you can specify, for one that you want to connect to a sync server or that you want to use the local database. I don’t think we have any use cases. You’d have a schema, they couldn’t be shared. You couldn’t have a game object that lived locally and a game object that lived in your object server, but maybe you have these local objects and then you’d have to do your own property mapping into the other objects. It’s not perfect, it’s not something we’ve considered.

Q: How would you copy data from one Realm to another in this case? Can you take an object from one, disconnect it from the live? Eric: You can disconnect it. You can copy it out so you can pass it anywhere and do anything you want, but to, it wouldn’t be that same object that you can put into a different Realm, you would have to map the properties. Copy each field. It’s not a typical use case that we see, but yes.

I was in the game room controller, and I was about to handle the invite. Somebody set themselves as my challenger. If you remember, we had a notification block set up so that any changes to me would listen and fire this block off, and the block checked. To see if our challenger was not nil. In this case, if it weren’t, then we will handle an invite from another player to start a game. And we’ll create a UI alert controller, saying you are invited to a game by whatever their name is, show it, and depending on if they say yes or no, we’ll either, if they say no, we’re going to cancel this, and by canceling, we’re going to remove that challenger from our object. If we want to say yes, then we’ll go ahead and create the game and it’s good.

We’re switching to Swift, because Marin’s made this more succinct than our Java side.

We’ll pass the two players that are going to be playing the game. As long as the other person is truly available, we’ll write in a transaction, the creation of this new game, and we’ll set that game object on both of our players. That setting of that game object is what’s causing those players to move into the game. The game object creation itself is creating all the numbers. They’re random each time.

They’re not the same numbers, and the placements aren’t the same. We create these numbers, we create both sides, including how many numbers do they have left, the full array at first, what’s the challenger, what’s the challenger ID, the player they’re tied to, etc. And then we return this game back.

Again, it’s set on this player. Our notification block’s fired, we have a current game, so we’ll move into the game controller, and then we’re launched and you’re into the game. We also have the game controller logic, too. It’s mostly logic built around making sure if somebody pops or loses or setting the score.

I wanted to see if I could launch the simulator, give somebody my phone, and see if we can play against each other. The winner will have their scores logged. And I have a JavaScript function or class over here that’s Node.js app listening to our object server, and any time a score comes in, it’s going to do something simple (e.g. write that score to a file, this board text). I have a Mac app that’s watching that text file for new things that come in, it will display here.

Let me go ahead and relaunch the iOS app.

RealmPop on the backend in Node.js

While that’s launching, I’m going to explain the RealmPop JS file. When I run this in Node, which I don’t know if I have it running yet. You saw the game I played that was reported once, it will report again as we go. When this runs, it’ll create this pop object that takes the Realm Object Server that we want to connect to, and databases we want to listen to.

In this case, we’re listening to any game database, and the star’s interesting. If we logged in as a different user, each user would get their own game database. Like our tasks app. They each get their own tasks database. But you can attach listeners to all the tasks databases. In this case, the game databases.

Even if they’re using different versions of the same schema, but specific to those users, you can listen to all of those on the server side, and perform aggregated events. Maybe you take that data out and send it into your backend.

When this launches, it’ll create this, and then it will do this connection using another way to authenticate, that I haven’t talked about, called a Realm admin token. Every Realm installation starts up with an admin token, that’s generated the first time it runs, and you can always reset it. This admin token should be considered secret because, if you use it to connect, you get an admin user that’s able to connect to any Realm database running on your object server.

I’m using this admin token. I’m connecting at our IP address on Digital Ocean. And when I perform the connection, I get this admin user using this admin token, I could have used user name and password here.

Then I’m adding a listener to our Realm object server. Using this admin user, connecting and listening to any game database changes. And when a change occurs, we’re going to call this callback, which looks for any changes to the score object.

If there’s a score update, then it pulls all scores out of the database (this should look similar to what we did on Swift and Android). We’ll iterate through those scores, we’ll log them to the console, and we’ll add them to this score text file, this board.text.

Once we write it to the text file, we’ll go ahead and delete the score so that we don’t report on that.

Round 2: Live Players

I have two people. Who wants to use my iPhone and challenge me?

If you want to challenge me, or I can challenge you, if you tap me, it should challenge me here. And I’m invited to a game. I should have done something first. Go ahead and hit back and put your real name in. You’re not IP6. Notice, as he’s changing his name, it’s changing it.

Keystroke by keystroke, that was in the transaction. You probably wouldn’t want to do that in a real world app. You want to wait until they enter their name. I did attach a change listener. I specifically did that so you could see how fast things are happening.

It is extremely fast. This is going to be about good architecture with the platform, and it’s an intro of the platform, what you can do with it, and how to get started with it. As you can see, we had a lot of code munched into view controllers, certainly we wouldn’t do that in a real world app, but it works great for demonstration, including the auto updating of the text.

Now you can challenge me. I will accept. And we’ll be in a game. This is my screen. You have your screen.

I’m going to walk us through it the first time. It looks like 15 is the largest number, so we’ll probably want to pop that. And you’ll see that as we’re going along, you can see his score and my score here. I have six left to go.

Q: The one you popped, should it pop on my device, as well? Eric: No. They’re different bubbles. You might have popped out of order.

We’re in the game. We’re going to look on here. Now our bubbles are in different spots. We’re going to look for the biggest number and pop that first. 11 is the biggest number. We’re using the same numbers, they’re in different positions.

After I pop 11, you see that you have six left to go, and I see that here, too. Then we can say pop eight because that’s the next one, and six, and five, and three, and I’m going to give this back to you. All you have to do is pop one zero and I’m going to see if I can get there.

Yes, pop one, then zero. Great. You popped in time at 41 and beat me out.

Key Features of Realm Platform

I didn’t cover some of the key features: authentication, username and password’s built in.

We integrate with Cloud Kit, Facebook, and Google, by default. But if you have your own third party IDP, identity providers, you can hook those in too.

We handle authorization at a Realm database level for any of the Realm object server databases. In terms of, can specific users read or write to that Realm, with sensible defaults. We have encryption, both across the wire and at rest. Your data’s always encrypted both on the device and in the object server.

Realtime synchronization when you’re online and when you’re offline, you’re working with your local database. With the professional edition and above, we have that server side event handling, so I can plug in that JavaScript.

We also have an integrations API that’ll plug into your existing databases and pull data in.

If you’re using us and you get popular and you have millions of people using your app, that’s great, with our Enterprise Edition, we have a horizontal scaling solution, which will cluster multiple object servers to handle additional load, and we have a load balancer we put in front of that. And we offer continuous backup for the Enterprise Edition. If you wanted to colo setup, a backup in case your main object servers go down, you can direct traffic over there.

Q: If I compare this with Firebase, you are the same. The probably one difference that you’re open source or I can post my data separately? Eric: There’s a couple of key differences to Firebase. Firebase is a schemaless architecture, so you’re saving JSON blobs. You have a lot of data redundancy. Firebase is faster for writing data in because it’s chucking JSON in, we’re faster for querying data. If you have an app that you have a lot of relationships between your objects and you’re doing a lot of querying. We are in bouncing between things, that’s almost free to traverse through object relationships with Realm versus Firebase, where it’s not.

The other big thing is their pricing is different. Our pricing is based on feature sets. And you can host it yourself, we don’t care how much data you’re using. With Firebase, of course, it’s part of a suite of products, but they base it on how much data and bandwidth and other things that you’re using, so some fine differences.

We do have primary keys. We have indexable fields because even though it’s an object database. If you have 100,000 objects, it’s going to be quicker if you index that to hash it, to pull it up. You can do stored procedures, and you can’t do aggregate queries like you could with SQL. It’s a different way of thinking about it.

We have other examples that we feel are more real world use case and business focused and definitely put together in a better architecturally way.

Check us out at realm.io. We have a tasks app, for example, where you would log in on any of your devices, and all those tasks would sync between your devices. Our database is free and open source, our platform, the developer edition is free, you can host it yourself. The professional edition with a few extra features has a free 60 day trial. And the enterprise edition, if you’re serious about using the platform, reach out to us.

Q: How much harder would it be for everyone to pop the same bubbles? Eric: It would have been harder. We would have to worry about conflict because if I popped a bubble and the other person popped a bubble at the same time, then if I was on the device that lost, that bubble would have had to reappear, and we would have had to handled that logic somehow.

Q: How does Realm core on traditional hardware? On SSD? thinking about running this on spinning rest hard drives. I know from reading about Realm Core, it seems to be designed specifically as a mobile database and assuming some flash memory or SST. Eric: I’ll have to reach out to the core team and see their thoughts on that, I don’t know off hand.

Q: Can you tune it so it will use more memory and less? Eric: No, it’s tuned in a way that we feel is going to be ideal for the mobile device that you’re running it on, and there’s no additional things, at least for the client. On the Realm Object Server, there is a bunch of server side configuration you can do for it.

We are hiring!

We’re a growing company. We started in 2011. We’re at 70 people now worldwide. And we have a huge backlog of features we want to implement. If you’re looking for something new, please reach us on Realm.io/jobs. We’re pretty distributed: San Francisco, Copenhagen, Denmark, and then we have people scattered across a globe (Barcelona, Canada, Australia, Korea, South Korea).

Q & A

Q: Roughly how many lines can you have connected at the same time to the database, one app server, roughly? Eric: We don’t have a good benchmark that I know. We don’t have a white paper or any study on it. I don’t know off hand what that max is. I have asked for it, and I know the sync team’s done some benchmarks on their own, but nothing published yet.

If you press the bubbles out of order, it adds two bubbles instead of ends the game. Right now we’re all pretty heads down with the tour; we’re running with the game, but it would be a cool app to refine and eventually it’ll be in our demos repo and open source.

Q: What’s the maximum number of players? Eric: For this game it’s two, but you could create your own game where it’s multiple. That would be fun. You’d have to find a different way to like show all the players in the game because we had one person on the left and one on the. If you had another way to display that, then everybody could be popping their own bubbles at the same time. That could be interesting.

Q: In the unlikely case that like things don’t sync up the way that you’d expect, do you have any insight into it? Like, aside from like seeing things on the server, can you look at like, get a log of like in what order this resolved on the server? Eric: Not accessible to your client code right now. You’d want to attach a notification block to fire or a change listener if you’re on Android to fire off when data changes. If it’s a data change that you don’t expect, based on your specific app circumstance, you’d have to react to it.

Q: You don’t have a sense of a public app? Like, there’s one instance? Eric: Like an anonymous connection? No, not yet. I think that is something that is on our road map. I don’t know what the timing of it.

Q: A while back you opened up like a registration pool for a public view of the C++ API. Is that still happening, or do you have plans to introduce the C++ API at some point? Eric: I don’t have a good answer. Let me get back to you on that.

Q: Is there anywhere where I could read about system authorization? Eric: We have on our website, separated by the mobile database and the mobile platform. There’s some paragraphs that talk about the different types of authentication. I don’t remember how much detail it goes into with third party custom identity provider authentication. I know that’s a feature with our enterprise edition. If you reach out to us, we’ll get back to you and answer some more questions, but we don’t have public pricing for that and we don’t have all of those features completely documented in terms of how to use because it’s mainly meant for enterprise customers. But if it’s something you’re interested, sign up and then we’ll reach out to you.

Q: How would your enterprise server integrate with a Microsoft server environment? IS? Google server? Eric: Our object server runs on Linux and on Mac. You would have to spin up some virtual box or physical box for the servicing of it. Because you can plug in other identity providers, we’re actively working on using active directory to be able to authenticate. And then you’d have to listen to changes coming in Realm and have a no JS thing that’s sending whatever restful requests on your backend or however you’re getting that into your Microsoft infrastructure, you’d have to do that yourself. Or you could write it directly to Sequel server from there.

Q: But it’d be listening to, on the server side, listening to the Realm database. Eric: Yes. But the idea of the object server is to handle that interaction across the internet, but once you’re in your nice cloud environment, we feel network reliability can be counted on better. You can use things like message queues to guarantee reliability of delivery. Hopefully it’s easier to get it into your backend, once it’s there.

Q: Do you have plans for Swift server support? Eric: I don’t think we have any definitive plans at this time, but it’s something we’ll consider if we get more and more. If you haven’t already opened a feature request issue (it’d be on the Realm object server, or the Realm Platform projects), then please do so and helps us know what our users want.

Next Up: Getting Started with the Realm Platform 2.0

General link arrow white

About the content

This content has been published here with the express permission of the author.

Eric Maxwell

Eric is an Product Engineer at Realm. He has spent over a decade architecting and developing software for various companies across different industries, including healthcare, insurance, library science, and private aviation. His current focus is training, mentoring, and mobile development. He has developed and taught courses on Java, Android and iOS. When he’s not working, he enjoys time with family, traveling and improv comedy.

4 design patterns for a RESTless mobile integration »

close