Realm Mobile Platformがリリースされた
これまでのクライアント独立のローカルDB機能に加えて
リアルタイムの同期、その場合に発生しうるコンフリクトの解決、イベントハンドリング等が出来るようになった

Realm Mobile Platform: リアルタイムの同期と、Coreのオープンソース化

イメージ的にはFirebaseのリアルタイム同期型データベースと同じようなものっぽいけど MBaasのようなクラウドサービス提供型ではないのでサーバは自前で運用する必要がある

デモアプリを動かしてみる

まずはrealm-mobile-platformのmacOS bundleをダウンロード

Realm Mobile Platform: Getting Started

解凍したファイル中のstart-object-server.commandを実行するとrealm-object-serverが起動し
ブラウザでlocalhost:8090/#startupが表示される

初回アクセス時にemailとpassを設定する

demo/RealmTasksの中のRealmTasks.appを起動して適当に動かしてみる

最初にusernameとpasswordを聞かれるので先ほど設定したemailとpassを入力し、TODOリストを幾つか登録してみる

ここで、同じく解凍したディレクトリの中にあるRealm Browserを開く
起動したらConnect to Object Server を選択

ServerURLにrealm://127.0.0.1:9080を指定

さらに

In order to connect as admin we need an admin access token. In the terminal running the server, look for a line starting with Your admin access token is:. Copy the long token key string

realm-object-serverを走らせてるターミナル上に記載されてるアクセストークンを
設定しろと書いてあるので確認してコピペしてAdmin Access Tokenに指定する

起動すると、先ほどデモアプリで入力したデータが登録されている
これはアプリ内のrealmファイルではなくサーバ側に連携されたデータになる

さらにiOS版のアプリもコードがあるのでシミュレータで起動してみる
ちなみに、ダウンロードしたディレクトリ内のiOSサンプルファイル群にPodfileが見つからなかったので Githubから持ってきた改めてソースを取得し直した

Github : RealmTasks

が、pod installでエラーになる
とりあえずPodfileのgit@としているところをhttpsに変更したら回避できた

pod 'Realm', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true
pod 'RealmSwift', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true

先ほどのmac版のデモアプリと同様にログインしてアプリを起動するとmacアプリで入力したデータが表示される
さらに片方でデータを追加、削除等の操作をすると
するともう片方のアプリで即座に反映するのが確認できた

実装手順をみてみる

詳細はこちらで
The Realm Mobile Platform

まず、Realm Object Serverへの接続URLを定義する

let serverURL = NSURL(string: "http://my.realmServer.com:9080")!

次に認証情報を設定する(ドキュメントをみると独自のid / pass以外にgoogleやfacebook、icloud等の認証も使えるっぽい)

let usernameCredential = Credential.usernamePassword(username: "username", password: "password", actions: [.createAccount])
let googleCredential   = Credential.google(token: "Google token")
let facebookCredential = Credential.facebook(token: "Facebook token")
let iCloudCredential   = Credential.iCloud(token: "iCloud token")

そして認証処理を行い成功した場合userインスタンスを取得する

User.authenticate(with: credential, server: serverURL) { user, error in
  if let user = user {
    // can now open a synchronized Realm with this user
  } else if let error = error {
    // handle error
  }
}

最後に、serverURLとuserインスタンスを使ってRealmのconfigurationを作成、realmインスタンスを作成する

// Create the configuration
let syncServerURL = URL(string: "realm://localhost:9080/~/userRealm")!
let config = Realm.Configuration(syncConfiguration: (user, syncServerURL))

// Open the remote Realm
let realm = try! Realm(configuration: config)

以降はこのrealmインスタンスを使えばデータの更新時にRealm Object Serverに連携されるようになる
ざっと実装方法を見ると単独で使用していた時とほとんど変わらずサーバ同期が簡単に可能になるようだった

その他雑感

コンフリクトについてはデフォルトでは以下のようなルールになるらしい
さらにルールのカスタマイズも出来るっぽい

Conflict Resolution

  • Deletes always wins
  • Last update wins
  • Inserts in lists are ordered by time
  • 一方で削除された場合は常に削除が優先される
  • 双方で更新がされた場合は最終更新が優先される
  • 同じ位置にデータが登録された場合は時間順になる

あとは、大規模なサービスになった時にどの程度のサーバスペックが必要なのかとかスケールアウトはどうするのか
ちなみに、↓を見るとproxy moduleはNginx等に置き換えることも可能なようだった Realm Object Server : Proxy
他にも気になるところは色々あるけど今回はとりあえずこの辺で。。。