Realm Object Server Setup In AWS Instance

Realm Object Server provides synchronisation of Realms between devices and provides authentication and access control services. Realm Object Server is a Node package which requires a Node project to run within.

Artboard.png

Prior knowledge


Mandatory to have some basic knowledge in linux commands which will help you to setup realm object server in AWS instance. Either you have AWS instance or CentOS instance to run below commands directly.

Ports

The Realm Object Server utilizes websocket connections over TCP to synchronize data. This means that you will need to make sure your firewall allows TCP communication over whichever ports your ROS is configured to use. By default, this is port 9080 for HTTP traffic. It is better securing your server by enabling HTTPs communication which is done over port 443.

Install Realm Object Server and Configure

Note:-  Don’t use root permission to run commands to setup ROS

  • #SSH to your instance
  • #Install NVM
    curl https://raw.githubusercontent.com/creationix/nvm/v0.25.0/install.sh | bash
    Note:- Close terminal and open once
  • #Install Node.js using NVM
    nvm install 8.11.3
  • #Install Node.js LTS
    curl –silent –location https://rpm.nodesource.com/setup_8.x | sudo bash –
    sudo yum -y install nodejs
  • #To compile and install native addons from npm
    sudo yum install gcc-c++ make
  • #Install realm-object-server using npm
    npm install -g realm-object-server
  • #Update realm-object-server to latest version
    npm install realm-object-server@latest
  • Note:- After installing ros you can check ros -V to find the version of ROS installed. If it throws error then you need to verify with some above steps.
  • #Go to html Directory
    cd  /var/www/html
  • #Create a new ROS project instance:
    ros init my-app
  • #Once my-app folder created go to my-app directory
    cd my-app
  • #Update feature token/access token in src/index.ts
  • #Start the server
    npm start

Running ROS in the Background

Once you are ready to go into production, you will want to daemonize your application project so that it runs in the background and automatically on server startup. It is  recommended using pm2 to maintain instances of Realm Object Server in production. PM2 is a battle tested process manager that allows your applications to stay alive forever and helps with mission critical administration during downtime.
  • #Install pm2
    sudo npm install pm2 -g
  • #From my-app directory run below command which will run ROS background
    pm2 start dist/index.js -n ros
  • #To check status of server running
    pm2 status
  • #To find your server logs file path
    pm2 describe 0
  • #To stop ROS
    pm2 stop ros
  • #To start ROS
    pm2 start ros

Once done you can browse your instance URL:9080 and it should look like this and in realm studio you will be able to login as well:

Screen Shot 2018-07-25 at 6.11.44 PM.png

References

https://docs.realm.io/platform/self-hosted/running-the-server

https://nodejs.org/en/download/package-manager/

https://www.liquidweb.com/kb/how-to-install-node-js-via-nvm-node-version-manager-on-centos-7

https://realm.io/

Advertisements

Node.js async await vs promise vs callback

Normally Node.js invokes functions asynchronously. Node.js async await, promise and callback comes into picture when you want to execute one function after completion of another function execution.

All these features are introduced one by one in Node.js different version release. Before Node version 7.6, the callbacks were the only way provided by Node to run one function after another.

We will see all three concepts taking real case scenario:

Three Tomatoes with Shadows --- Image by © Royalty-Free/Corbis

Requirement is If you have sufficient balance then you can purchase. All examples below written can not be directly executed rather used here to show concept difference.

Ex:

let placeAnOrderAndDeliver = function(name, address) {
  // Send the item to Dear 'name' staying at this 'address'
}

let showWarningOrError = function(statusCode, error) {
  // Show warning message or error message if no sufficient balance
  // Or if any error happened
}

let checkSufficientBalanceInAccount = function(
    userName, password, balanceNeeded, callback) {
  if (logInCredentialValidated) {
    if (balanceInMyAccount > balanceNeeded) {
      callback(true);
    } else {
      callback(false);
    }
  } else {
    callback(false);
  }
}

let purchaseItem = function(itemName, itemCost) {
  try {
    checkSufficientBalanceInAccount('testUser', 'testPassword', itemCost,
        function(response) {
          if (response) {
            placeAnOrderAndDeliver('Name', 'Address');
          } else {
            showWarningOrError('402', 'Insufficient balance!')
          }
        })
  } catch (error) {
    showWarningOrError('400', error.message)
  }
}

Problem of above way is, for multiple callbacks it gets messy and cause lot of troubles.

Later promise and function chaining introduced in Node.js version:

So if you will refactor above functions into promise and function chaining, it will look like this:

let placeAnOrderAndDeliver = function(name, address) {
  // Send the item to Dear 'name' staying at this 'address'
}

let showWarningOrError = function(statusCode, error) {
  // Show warning message or error message if no sufficient balance
  // Or if any error happened
}

let checkSufficientBalanceInAccount = new Promise((resolve, reject) => {
  let successMsg = {
    status: '200',
    message: 'Successful transaction!'
  };

  let failureMsg = {
    status: '449',
    message: 'Unsuccessful transaction!'
  };

  let failureLoginMsg = {
    status: '401',
    message: 'Invalid credential!'
  };

  if (logInCredentialValidated) {
    if (balanceInMyAccount > balanceNeeded) {
      resolve(successMsg);
    } else {
      reject(failureLoginMsg);
    }
  } else {
    reject(failureMsg);
  }
});

let purchaseItem = function(itemName, itemCost) {
  try {
    checkSufficientBalanceInAccount('testUser', 'testPassword', itemCost).
        then((response) => {
          placeAnOrderAndDeliver('Name', 'Address');
        }).
        catch((reason) => {
          showWarningOrError(reason.status, reason.message);
        });
  }
  catch (error) {
    showWarningOrError('400', error.message);
  }
};

In this way code looks more clear and easily understandable. You can chain multiple functions by adding multiple .then

In Node v8 await gets released to deal with promise and chaining. Here no need to write .then, Simply you need to call prefix await before the function name and call next function usually you call the function. Unless await function executes the next function will not be executed.

Example using async/await:

let placeAnOrderAndDeliver = function(name, address) {
  // Send the item to Dear 'name' staying at this 'address'
}

let showWarningOrError = function(statusCode, error) {
  // Show warning message or error message if no sufficient balance
  // Or if any error happened
}

let checkSufficientBalanceInAccount = new Promise((resolve, reject) => {
  let successMsg = {
    status: '200',
    message: 'Successful transaction!'
  };

  let failureMsg = {
    status: '449',
    message: 'Unsuccessful transaction!'
  };

  let failureLoginMsg = {
    status: '401',
    message: 'Invalid credential!'
  };

  if (logInCredentialValidated) {
    if (balanceInMyAccount > balanceNeeded) {
      resolve(successMsg);
    } else {
      reject(failureLoginMsg);
    }
  } else {
    reject(failureMsg);
  }
});

let purchaseItem = async function(itemName, itemCost) {
  try {
    await checkSufficientBalanceInAccount('testUser', 'testPassword', itemCost);
    placeAnOrderAndDeliver('Name', 'Address');
  }
  catch (error) {
    showWarningOrError('400', error.message);
  }
};

If you will compare promise based example and async/await based example then you will find last function is the main difference where “let purchaseItem = async function” you can see async keyword before function keyword. Because await should be used inside async function.

Another difference is functions are called in an order, where function called after await function will not execute unless await function completes.

That is all about basic usage and main differences. If you want to know more about promise and async/await go through these references links:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Hope you like it!

Thanks for your time to go through this.

Use of realm object in realm Event handler

Before describing the deep concept of handling realm event handler changes, if you want to know about realm then please go through these links https://realm.io/ and https://realm.io/docs/javascript/latest/once.

Realm Platform:

They provide new standard in data synchronisation. Realm helps companies build engaging mobile applications with minimal development time. The Realm Platform enables any development team, no matter the size, to include difficult-to-build features like two‑way data sync and realtime collaboration. Devote more time to what makes your app truly unique and less time to maintaining services.

Realm object database is a simple alternative to SQLite and Core Data and proudly open source.

I can just share the benefits of realm database quickly:Screen Shot 2018-06-23 at 10.06.14 AM

Now let’s discuss about handling event handler changes:

This is an important and awesome feature which you will not find in any other mobile DB like sqlite, Oracle Lite, Tiny DB etc.

Once you setup realm database and connect to realm DB using Node JS then for any changes in database, the event fires for that change and you can capture that event change in callback.  If you have multiple databases or individual database for each user then you can set the path to register the event change for those databases.

So for each operation(Insertion, Modification and Delete) in database there will be event fired and in callback of that you can do your operation in Node Js. For example if there is data insertion in realm DB through mobile then in Node Js server you can catch the data and insert that data to MySql or move to AWS SQS or play with it.

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 /~/myuserDB. It will look for updated Coupon objects in these Realms, verify their coupon code if it wasn’t verified yet, and write the result of the verification into the isValid property of the Coupon object.

'use strict';
var Realm = require('realm'); 

// the URL to the Realm Object Server
var SERVER_URL = '//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 = '^/([^/]+)/myUserDB$';

//declare admin user
let adminUser = undefined

// 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
var handleChange = async function (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("^/([^/]+)/([^/]+)$");
  var userId = matches[1];

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

  for (let couponIndex of 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;
      });
    }
  }
}

function verifyCouponForUser(coupon, userId) {
    //logic for verifying a coupon's validity
}

// register the event handler callback
async function main() {
    adminUser = await Realm.Sync.User.login(`https:${SERVER_URL}`, 'realm-admin', '')
    Realm.Sync.addListener(`realms:${SERVER_URL}`, adminUser, NOTIFIER_PATH, 'change', handleChange);
}

main()

Note: In above code var realm = changeEvent.realm; where realm is the object which contains all rows, values which was changed in DB and other informations as well. So in event handler file no need to open realm to get realm object or to do any DB operation. You can use above realm object through out the event handler file carefully.

In past we did same mistake when dealing with realm object. Like

Realm.open({schema: [Car, Person]})
  .then(realm => {
    // ...use the realm instance here
  })
  .catch(error => {
    // Handle the error here if something went wrong
  });

So you no need to open realm in Event handler file unless you need it. As you can see the object realm already available var realm = changeEvent.realm;  globally.

For any DB operation like insertion, modification and delete operation you can use above realm object.

References:

https://realm.io/docs/javascript/latest/
https://academy.realm.io/posts/realm-sf-tim-oliver-event-handling-realm-object-server/https://docs.realm.io/platform/using-synced-realms/server-side-usage/data-change-events

Hope you like the post and stay tuned for my next post about “deep analysisof handling event handler for each DB operations”.

Thanks!