These features are limited to the Realm Mobile Platform Professional and Enterprise editions. Learn more about them and start a free trial.

Note: This documentation section only describes features specific to the Enterprise and Professional Editions. For other topics, including configuration, general usage, and troubleshooting, read the main Object Server documentation.

Installing/Upgrading

Note: The Professional and Enterprise editions of the Realm Object Server are currently available for Linux only.

Quickstart Installation

These instructions will walk you through quickly installing the Enterprise Edition along with the Continuous Backup client and server on the same machine, enabling them with the default configurations.

# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server and the backup client
sudo yum -y install realm-object-server-enterprise
sudo yum -y install realm-object-server-backup-client

# Enable and start the ROS service
sudo chkconfig realm-object-server on
sudo service realm-object-server start

# Enable and start the backup server service
sudo chkconfig realm-object-server-backup-server on
sudo service realm-object-server-backup-server start

# Enable and start the backup client service
sudo chkconfig realm-object-server-backup-client on
sudo service realm-object-server-backup-client start

# Check that the files are in sync
md5sum /var/lib/realm/object-server/0/user_data/__admin.realm
md5sum /var/lib/realm/object-server-backup-client/0/user_data/__admin.realm
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server and the backup client
sudo yum -y install realm-object-server-enterprise
sudo yum -y install realm-object-server-backup-client

# Enable and start the ROS service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

# Check that the backup server service is running
sudo systemctl status realm-object-server-backup-server

# Enable and start the backup client service
sudo systemctl enable realm-object-server-backup-client
sudo service realm-object-server-backup-client start

# Check that the files are in sync
md5sum /var/lib/realm/object-server/0/user_data/__admin.realm
md5sum /var/lib/realm/object-server-backup-client/0/user_data/__admin.realm
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-object-server-enterprise
sudo apt-get install realm-object-server-backup-client

# Enable and start the ROS service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

# Check that the backup server service is running
sudo systemctl status realm-object-server-backup-server

# Enable and start the backup client service
sudo systemctl enable realm-object-server-backup-client
sudo service realm-object-server-backup-client start

# Check that the files are in sync
md5sum /var/lib/realm/object-server/0/user_data/__admin.realm
md5sum /var/lib/realm/object-server-backup-client/0/user_data/__admin.realm

Upgrading to Professional Edition

This feature is limited to our Professional and Enterprise editions. Learn more about them and start a free trial.

If you are upgrading to the Professional Edition of the Realm Object Server, you must first uninstall the Developer Edition. Then, using the access token you’ve received from us via email, follow these steps according to your distribution:

# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-professional

# Enable and start the service
sudo chkconfig realm-object-server on
sudo service realm-object-server start
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-professional

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-object-server-professional

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

Upgrading to Enterprise Edition

If you are upgrading to the Enterprise Edition of the Realm Object Server, you must first uninstall the Developer/Professional Edition. Then, using the access token you’ve received from us via email, follow these steps according to your distribution:

# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-enterprise

# Enable and start the service
sudo chkconfig realm-object-server on
sudo service realm-object-server start
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-enterprise

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's package repository
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-object-server-enterprise

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

Load Balancing

This feature is limited to our Enterprise editions. Learn more.

The Realm Object Server has extremely high performance; even a single instance can handle tens of thousands of concurrent connections. However, for applications that expect millions of concurrent connections, multiple Object Servers are required. The Enterprise Edition of Realm Mobile Platform offers integrated load balancing, which allows you to horizontally scale to any number of Object Server instances.

Installation

Each node in a load balancing cluster runs a standalone instance of the Realm Sync Worker. This synchronization worker normally runs as part of Realm Object Server, synchronizing Realms between the server and Realm Mobile Database Clients; in its standalone form, it performs load balancing for an Object Server. Each load balancer runs its own instance of Sync Worker, all communicating with the Object Server instance.

The realm-sync-worker package must be installed from the Realm enterprise repository.

# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server standalone sync worker:
sudo yum -y install realm-sync-worker

# Replace /etc/realm/token-signature.pub with the one from the Realm Object
# Server.

# Enable and start the service
sudo chkconfig realm-sync-worker on
sudo service realm-sync-worker start
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server standalone sync worker:
sudo yum -y install realm-sync-worker

# Replace /etc/realm/token-signature.pub with the one from the Realm Object
# Server.

# Enable and start the service
sudo systemctl enable realm-sync-worker
sudo systemctl start realm-sync-worker
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-sync-worker

# Replace /etc/realm/token-signature.pub with the one from the Realm Object
# Server.

# Enable and start the service
sudo systemctl enable realm-sync-worker
sudo systemctl start realm-sync-worker

Configuration

In the Realm Object Server’s configuration.yml file, the sync.servers section describes the cluster of load balancers. Each balancing node must be identified with a unique ID, which can be any string as long as it is a valid filesystem path component.

Example:

sync:
  servers:
  - id: 'alpha'
    address: '::'
    port: 7800
  - id: 'beta'
    address: 'beta.local'
    port: 7800
  - id: 'delta'
    address: 'delta.local'
    port: 7800

If the address field designates an IP address representing all interfaces, i.e. “0.0.0.0” (or “::” if using IPv6), this indicates to the Realm Object Server that a local synchronization worker should be started listening on the IP address of localhost (“127.0.0.1” or “::1” respectively).

The sync workers only require additional configuration if multiple workers are started on a single instance, or if they should listen on an interface other than 127.0.0.1.

The example configuration files provided as part of the Realm Object Server installation provide additional details.

High Availability

One of the unique aspects of Realm Mobile Platform is that it is designed to be offline-first. Architecturally, clients retain a local copy of data from the server and read or write directly to their copy. The client SDK then sends the changes asynchronously when network connectivity is available and Realm Object Server automatically integrates these changes in a deterministic manner. Such a system is inherently highly available from the perspective of the client. Reads and writes can always occur locally irrelevant of the network conditions or server operations.

Realm is currently working on a clustering solution that supports automatic failover. This functionality will be available in the Enterprise Edition. To learn more and get early access, please contact us.

Continuous Backup

This feature is limited to our Enterprise editions. Learn more.

The Enterprise Edition of Realm Object Server includes a backup server running alongside the main process. This server monitors the state of a running Object Server, sending changes asynchronously to one or more backup clients. All clients maintain a slightly delayed copy of the server state.

You may continue to use the Manual Backup system described in the main Object Server documentation with the Enterprise Edition. (Manual backup is the only backup system provided for the Professional and Developer Editions.)

The continuous backup system communicates without encryption and authenticated access! To stay secure, run the backup system behind a firewall.

Backup Server

The backup server is installed as part of the realm-object-server and the realm-sync-worker. To enable it, run:

sudo chkconfig realm-object-server-backup-server on
sudo service realm-object-server-backup-server start
# Starts automaticaly when starting the realm-object-server
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
sudo systemctl status realm-object-server-backup-server
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
sudo systemctl status realm-object-server-backup-server

The configuration is done in the Realm Object Server YAML file (/etc/realm/configuration.yml) under the backup section. The keys used by the backup server are:

Configuration key Default Description
backup.enable true Set to false to disable backup.
backup.network.listen_address 127.0.0.1 The IP address/interface
backup.network.listen_port 27810 The listening port of the backup
backup.logging.level info Logging levels described in Logging
backup.logging.path /var/log/realm-object-server-backup-server.log (Linux) Log file path. Empty value for stderr.

If backing up a node in a cluster of sync workers, the backup server will read the sync worker configuration file instead, located at /etc/realm/sync-worker-configuration.yml.

Backup Client

The Realm Object Server Backup Client is started on every machine where a backup is needed. The backup client is configured in a separate YAML file.

To install the backup client, you need to setup the enterprise repository as described above.

# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server Backup Client
sudo yum -y install realm-object-server-backup-client

# Edit the configuration to point to an ROS with backup enabled. The default configuration assumes ROS and the Backup Server live on the same machine.
vim /etc/realm/object-server-backup-client.yml

# Enable and start the service
sudo chkconfig realm-object-server-backup-client on
sudo service realm-object-server-backup-client start
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-backup-client

# Edit the configuration to point to an ROS with backup enabled. The default configuration assumes ROS and the Backup Server live on the same machine.
vim /etc/realm/object-server-backup-client.yml

# Enable and start the service
sudo systemctl enable realm-object-server-backup-client
sudo systemctl start realm-object-server-backup-client
# Set the token variable:
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Setup Realm's Enterprise package repository. No need to do it if you already installed the ROS Enterprise.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-object-server-backup-client

# Edit the configuration to point to an ROS with backup enabled. The default configuration assumes ROS and the Backup Server live on the same machine.
vim /etc/realm/object-server-backup-client.yml

# Enable and start the service
sudo systemctl enable realm-object-server-backup-client
sudo systemctl start realm-object-server-backup-client

The configuration file is in /etc/realm/object-server-backup-client.yml.

The keys of the backup client configuration are

Configuration key Default Description
storage.root_path   The directory where the backup should be stored. A recovered Realm Object Server can be started with this directory as root path.
network.server_address   The IP address/interface of the backup server.
network.server_port 27810 The IP address/interface of the backup server.
network.reconnect_delay 2000 The delay (in milliseconds) between attempts to reach the backup server. The client automatically reconnects after connection loss.
logging.level info Logging levels described in Logging
logging.path /var/log/realm-object-server-backup-client.log (Linux) Log file path. Empty value outputs to stderr.

Monitoring

Realm Object Server supports sending metrics to statsd, which is assumed to be listening at localhost:8125. You can then forward these metrics to graphite or similar systems for monitoring.

All metrics keys start with a prefix of realm.<hostname>:

realm.example.com.server.connection.accept.succeeded
realm.example.com.server.connection.accept.failed
realm.example.com.server.protocol.bind.received
realm.example.com.auth.password.attempted
realm.example.com.auth.password.failed
realm.example.com.auth.password.failure.username_invalid
realm.example.com.auth.password.failure.password_check_failed

Counters

This counter is incremented when the Realm Object Server is started.

  • <prefix>.server.started

These counters are incremented when synchronization fails to start. This indicates the clients need to delete their Realm files and reload them from the server.

  • <prefix>.protocol.ident.failure.bad_server_version
  • <prefix>.protocol.ident.failure.diverging_histories
  • <prefix>.protocol.ident.failure.bad_client_file_ident

These counters are incremented when sessions start and terminate. A session is considered to start on connection, before authentication.

  • <prefix>.session.started
  • <prefix>.session.terminated

These counters indicate token-related failures.

  • <prefix>.protocol.client.token.failure.invalid_base64
  • <prefix>.protocol.client.token.failure.invalid_json
  • <prefix>.protocol.client.token.failure.missing_key: a token accepted without authentication because the key is missing
  • <prefix>.protocol.client.token.failure.signature_mismatch
  • <prefix>.protocol.client.token.failure.expired

These counters indicate different types of synchronization protocol messages sent/received.

  • <prefix>.protocol.download.sent
  • <prefix>.protocol.bind.received
  • <prefix>.protocol.client.received
  • <prefix>.protocol.ident.received
  • <prefix>.protocol.mark.received
  • <prefix>.protocol.refresh.received
  • <prefix>.protocol.unbind.received
  • <prefix>.protocol.upload.received

These counters track failures during protocol message processing.

  • Bind
    • <prefix>.protocol.bind.failure.bad_authentication
    • <prefix>.protocol.bind.failure.illegal_realm_path
    • <prefix>.protocol.bind.failure.permission_denied
    • <prefix>.protocol.bind.failure.reuse_of_session_ident
    • No token_expired counter here, because the token has not been provided yet. But the token provided with the bind message is checked and bad_authentication is raised if it is expired or invalid.
  • Ident
    • <prefix>.protocol.ident.failure.bad_server_file_ident
    • <prefix>.protocol.ident.failure.bound_in_other_session
    • <prefix>.protocol.ident.failure.permission_denied
    • <prefix>.protocol.ident.failure.token_expired
  • Refresh
    • <prefix>.protocol.refresh.failure.bad_authentication
    • <prefix>.protocol.refresh.failure.permission_denied
    • No token_expired counter here, because it is not considered an error to provide a new token while the current one has already expired. But the token provided with the refresh message is checked and bad_authentication is raised if it is expired or invalid.
  • Upload
    • <prefix>.protocol.upload.failure.bad_changeset
    • <prefix>.protocol.upload.failure.bad_client_version
    • <prefix>.protocol.upload.failure.bad_server_version
    • <prefix>.protocol.upload.failure.permission_denied
    • <prefix>.protocol.upload.failure.token_expired
  • Mark
    • <prefix>.protocol.mark.failure.token_expired

These counters track low-level protocol errors.

  • <prefix>.protocol.read.head.error.bad_message_before_activation
  • <prefix>.protocol.read.head.error.bad_session_ident
  • <prefix>.protocol.read.head.error.bad_syntax
  • <prefix>.protocol.read.head.error.ident_message_after_activation
  • <prefix>.protocol.read.head.error.limits_exceeded
  • <prefix>.protocol.read.head.error.message_after_unbind
  • <prefix>.protocol.read.head.error.premature_ident_message
  • <prefix>.protocol.read.head.error.unknown_message
  • <prefix>.protocol.read.head.error.wrong_protocol_version

Every protocol error counts against either connection.errored or session.errored.

  • <prefix>.protocol.connection.errored
  • <prefix>.protocol.session.errored

Lastly, these counters track connection events.

  • <prefix>.connection.accept.failed
  • <prefix>.connection.accept.succeeded
  • <prefix>.connection.read.failure.limits_exceeded
  • <prefix>.connection.read.failed
  • <prefix>.connection.write.failed
  • <prefix>.connection.started
  • <prefix>.connection.terminated
  • <prefix>.connection.removed

Gauges

The number of connections/sessions currently open. Multiple sessions can be served through a connection.

  • <prefix>.connection.opened
  • <prefix>.session.opened

Enabling Professional and Enterprise APIs

To use the Event Handling, Data Access and Data Connector features in Node.js applications, you must enable the APIs by including your access token in the application. (This token is sent to you via email when you sign up for a trial or purchase the Professional or Enterprise editions.) Near the start of your Node.js application, include your token and make a setAccessToken call to the Object Server:

var token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// Unlock Professional Edition APIs
Realm.Sync.setAccessToken(token);

The access token could also be loaded from a file rather than stored in your code:

RealmSync.setAccessToken(fs.readFileSync('./access-token', 'utf-8'));

Event Handling

An exclusive feature of the Enterprise and Professional Editions of Realm Object Server is event handling capabilities. This functionality is provided in the server-side Node.js SDK via a global event listener API which hooks into the Realm Object Server, allowing you to observe changes across Realms. This could mean listening to every Realm for changes, or Realms that match a specific pattern. For example, if your app architecture separated user settings data into a Realm unique for each user where the virtual path was /~/settings, then a listener could be setup to react to changes to any user’s settings Realm.

Whenever a change is synchronized to the server, it triggers a notification which allows you to run custom server-side logic in response to the change. The notification will inform you about the virtual path of the updated Realm and provide the Realm object and fine-grained information on which objects changed. The change set provides the object indexes broken down by class name for any inserted, deleted, or modified object in the last synchronized transaction.

Creating an Event Handler

To use Realm Event Handling, you’ll need to create a small Node.js application.

Create a directory to place the server files, then create a file named package.json. This JSON file is used by Node.js and npm, its package manager, to describe an application and specify external dependencies.

You can create this file interactively by using npm init. You can also fill in a simple skeleton file yourself using your text editor:

{
    "name": "MyApp",
    "version": "0.0.1",
    "main": "index.js",
    "author": "Your Name",
    "description": "My Cool Realm App",
    "dependencies": {
        "realm": "file:realm-1.0.0-professional.tgz"
    }
}

We specify the downloaded archive of the Realm Mobile Platform as a file: dependency; that archive should be in the same directory as the package.json file. (Make sure the filename specified in package.json is the filename that’s actually on disk!)

If you have other dependencies for your application, specify them in the dependencies section of this file.

After the package.json file is configured properly, type:

npm install

to download, unpack and configure all the modules and their dependencies.

Your event handler will need to access the Object Server with administrative privileges, so you’ll need to get the Object Server’s admin token. Under Linux, view the token with:

cat /etc/realm/admin_token.base64

On macOS, the token is stored in the realm-object-server folder, inside the Realm Mobile Platform folder. Navigate to that folder and view the token:

cd path-to/realm-mobile-platform
cat realm-object-server/admin_token.base64

A sample index.js file might look something like this. This example listens for changes to a user-specific private Realm at the virtual path /~/private. It will look for updated Coupon objects in these Realms and verify their code, if it wasn’t verified yet and write the result of the verification into the isValid property of the Coupon object.

var Realm = require('realm');

var ACCESS_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// Unlock Professional Edition APIs
Realm.Sync.setAccessToken(ACCESS_TOKEN); 

// Insert the Realm admin token here
//   Linux:  cat /etc/realm/admin_token.base64
//   macOS:  cat realm-object-server/admin_token.base64
var ADMIN_TOKEN = 'ADMIN_TOKEN';

// the URL to the Realm Object Server
var SERVER_URL = 'realm://127.0.0.1:9080';

// The regular expression you provide restricts the observed Realm files to only the subset you
// are actually interested in. This is done in a separate step to avoid the cost
// of computing the fine-grained change set if it's not necessary.
var NOTIFIER_PATH = '/^\/([0-9a-f]+)\/private$/';

// The handleChange callback is called for every observed Realm file whenever it
// has changes. It is called with a change event which contains the path, the Realm,
// a version of the Realm from before the change, and indexes indication all objects
// which were added, deleted, or modified in this change
function handleChange(changeEvent) {
  // Extract the user ID from the virtual path, assuming that we're using
  // a filter which only subscribes us to updates of user-scoped Realms.
  var matches = changeEvent.path.match(/^\/([0-9a-f]+)\/private$/);
  var userId = matches[1];

  var realm = changeEvent.realm;
  var coupons = realm.objects('Coupon');
  var couponIndexes = changeEvent.changes.Coupon.insertions;

  for (var couponIndex in couponIndexes) {
    var coupon = coupons[couponIndex];
    if (coupon.isValid !== undefined) {
      var isValid = verifyCouponForUser(coupon, userId);
      // Attention: Writes here will trigger a subsequent notification.
      // Take care that this doesn't cause infinite changes!
      realm.write(function() {
        coupon.isValid = isValid;
      });
    }
  }
}

// create the admin user
var adminUser = Realm.Sync.User.adminUser(adminToken);

// register the event handler callback
Realm.Sync.addListener(SERVER_URL, adminUser, NOTIFIER_PATH, 'change', handleChange);

console.log('Listening for Realm changes');

Integrating With Another Service

For a complete example of integrating the Event Handling framework with another service (in this case, IBM Watson’s Bluemix), read the tutorial for the Scanner App.

Data Access

The Professional and Enterprise Editions of the Realm Object Server allow you to access and change any shared Realm server-side using the administration token generated when you start the server. This allows access to all data in that Realm.

To retrieve the admin token on Linux:

cat /etc/realm/admin_token.base64

On macOS the token is stored in the realm-object-server folder within the zip:

cat realm-object-server/admin_token.base64

This can be used to synchronously construct a Realm.Sync.User object which can be passed into the Realm constructor to open a connection to any Realm on the server side.

// Open a Realm using the admin user
var adminToken = '3x4mpl3T0k3n…';
var adminUser = Realm.Sync.User.adminUser(adminToken);
var realm = new Realm({
  sync: {
    user: admin_user,
    url: 'realm://object-server-url:9080/my-realm',
  },
  schema: [{...}
  }]
});

Note that when used with an admin user, the Realm URL does not include the ~ character that resolves into the user ID for non-admin authentication; the admin user does not have a user ID. For non-admin authentication, read the Authentication section in the Object Server Access Control documentation.

Data Connector

This feature is limited to our Enterprise editions. Learn more.

The Enterprise Edition of the Realm Object Server offers a Node.js-based adapter API that allows you to access all low-level Object Server operations and data. This can be used to let a synced Realm interact with an existing legacy database such as PostgreSQL: the Realm will also be kept in sync with the external database in real time. Client applications can use the Realm Mobile Database API and get the benefits of working with real-time, native objects.

The Adapter API is set up in a very similar fashion to the Event Handler API described above. Create a small Node.js application by creating a directory to place the server files, then create a package.json for npm dependencies or use npm init to create it interactively. You’ll need to specify the Realm Mobile Platform EE Edition as a file: dependency, with the archive in the same directory as the package.json file. (Make sure the filename specified in package.json is the filename that’s actually on disk!)

{
    "name": "MyApp",
    "version": "0.0.1",
    "main": "index.js",
    "author": "Your Name",
    "description": "My Cool Realm App",
    "dependencies": {
        "realm": "file:realm-1.0.0-enterprise.tgz"
    }
}

After your other dependencies are specified, use npm install to download, unpack and configure the modules.

As with the event handler API, you’ll need to access the Object Server with administrative privileges, and will need to get the Object Server’s admin token. Under Linux, view the token with:

cat /etc/realm/admin_token.base64

On macOS, the token is stored in the realm-object-server folder, inside the Realm Mobile Platform folder. Navigate to that folder and view the token:

cd path-to/realm-mobile-platform
cat realm-object-server/admin_token.base64

To use the Adapter API, the Node.js application you’re creating will act as a translator, receiving instructions from the Object Server and calling your external database’s API to read and write to it. A sample application might look like this:

var Realm = require('realm');

var ACCESS_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// Unlock Professional Edition APIs
Realm.Sync.setAccessToken(ACCESS_TOKEN); 

var adapterConfig = {
  // Insert the Realm admin token here
  //   Linux:  cat /etc/realm/admin_token.base64
  //   macOS:  cat realm-object-server/admin_token.base64
  admin_token: 'ADMIN_TOKEN',

  // the URL to the Realm Object Server
  server_url: 'realms://127.0.0.1:9080',

  // local path for the Adapter API file
  local_path: './adapter',

  // regular expression to limit which Realms will be observed
  realm_path_regex: '/^\/([0-9a-f]+)\/private$/'
};

class CustomAdapter {
  constructor(config) {
    this.adapter = new Realm.Sync.Adapter(
      config.local_path,
      config.server_url,
      Realm.Sync.User.adminUser(config.admin_token),
      config.realm_path_regex,

      // This callback is called any time a new transaction is available for
      // processing for the given path. The argument is the path to the Realm
      // for which changes are available. This will be called for all Realms
      // which match realm_path_regex.
      (realm_path) => {
        var current_instructions = this.adapter.current(realm_path);
        while (current_instructions) {
          // if defined, process the current array of instructions
          this.process_instructions(current_instructions);

          // call advance to progress to the next transaction
          this.adapter.advance(realm_path);
          current_instructions = this.adapter.current(realm_path);
        }
      }
    )
  }

  // This method is passed the list of instructions returned from
  // Adapter.current(path)
  process_instructions(instructions) {
    instructions.forEach((instruction) => {
        // perform an operation for each type of instruction
        switch (instruction.type) {
          case 'INSERT':
            insert_object(instruction.object_type, instruction.identity, instruction.values);
            break;
          case 'DELETE':
            delete_object(instruction.object_type, instruction.identity);
            break;
          // ... add handlers for all other relevant instruction types
          default:
            break;
        }
      })
  }
}

Each instruction object returned by Adapter.current has a type property which is one of the following strings. Two or more other properties containing data for the instruction processing will also be set.

  • INSERT: insert a new object
    • object_type: type of the object being inserted
    • identity: primary key value or row index for the object
    • values: map of property names and property values for the object to insert
  • SET: set property values for an existing object
    • object_type: type of the object
    • identity: primary key value or row index for the object
    • values: map of property names and property values to update for the object
  • DELETE: delete an exising object
    • object_type: type of the object
    • identity: primary key value or row index for the object
  • CLEAR: delete all objects of a given type
    • object_type: type of the object
  • LIST_SET: set the object at a given list index to an object
    • object_type: type of the object
    • identity: primary key for the object
    • property: property name for the list property to mutate
    • list_index: list index to set
    • object_identity: primary key or row number of the object being set
  • LIST_INSERT: insert an object in the list at the given index
    • object_type: type of the object
    • identity: primary key for the object
    • property: property name for the list property to mutate
    • list_index: list index at which to insert
    • object_identity: primary key or row number of the object to insert
  • LIST_ERASE: erase an object in the list at the given index: this removes the object
  • from the list but the object will still exist in the Realm
    • object_type: type of the object
    • identity: primary key for the object
    • property: property name for the list property to mutate
    • list_index: list index which should be erased
  • LIST_CLEAR: clear a list removing all objects: objects are not deleted from the Realm
    • object_type: type of the object
    • identity: primary key for the object
    • property: property name for the list property to clear
  • ADD_TYPE: add a new type
    • object_type: name of the type
    • primary_key: name of primary key property for this type
    • properties: Property map as described in Realm.ObjectSchema
  • ADD_PROPERTIES: add properties to an existing type
    • object_type: name of the type
    • properties: Property map as described in Realm.ObjectSchema
  • CHANGE_IDENTITY: change the row index for an existing object: not called for objects with primary keys
    • object_type: type fo the object
    • identity: old row value for the object
    • new_identity: new row value for the object

For full details, including all the instruction types and the data passed to them, consult the API reference for the Realm.Sync.Adapter class.

A PostgreSQL data connector is already implemented, and more are on the way, including MongoDB and Microsoft SQL Server. Any data connector can be customized to your application’s specific needs. If you’re a Realm Enterprise customer, contact your representative for more information.