Categories
NodeJS

NodeJS: Generator Based Workflow

This post assumes you already know about Promises, Generators and aims at focusing more on the `co` library and the generator based workflow it supports. If you are not very familiar with Promises or Generators, I would recommend you study them first.

Promises are nice

Promises can save us from the callback hell and allow us to write easy to understand codes. May be something like this:

function promisedOne() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 3000);
  })
}

promisedOne().then(console.log);

Here we have a `promisedOne` function that returns a `Promise`. The promise is resolved after 3 seconds and the value is set to 1. For keeping it simple, we used `setTimeout`. We can imagine other use cases like network operations where promises can be handy instead of callbacks.

Generator Based Workflow

With the new ES2015 generators and a nice generator based workflow library like `co` (https://github.com/tj/co) , we can do better. Something like this:

const co = require('co');

function promisedOne() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 3000);
  })
}

function * main() {
  try {
    let promised_value = yield promisedOne();
    console.log(promised_value)
  } catch (e) {
    console.error(e);
  }

}

co(main)

What’s happening here? The `co` function takes a generator function and executes it. Whenever the generator function `yield`s something, `co` checks if the object is one of the `yieldables` that it supports. In our case, it’s a `Promise` which is supported. So `co` takes the yielded promise, processes it and returns the results back into the generator. So we can grab the value from the yield expression. If the promise is rejected or any error occurs, it’s thrown back to the generator function as well. So we could catch the error.

`co` returns a `Promise`. So if the generator function returns any values for us, we can retrieve those using the promise APIs.

function * returnSomething() {
  return "Done"
}

co(returnSomething).then(console.log);

// Or

co(function * () {
  return "Something else"
}).then(console.log);


// Let's make it a little more complex

co(function *() {
  return yield new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 3000);
  })
}).then(console.log);

So basically, we yield from the `yieldables`, catch any errors and return the values. We don’t have to worry about how the generator is working behind the scene.

The `co` library also has an useful function – `co.wrap`. This function takes a generator function but instead of executing it directly, it returns a general function which returns a promise.

const co = require('co');

function promisedOne() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 3000);
  })
}

const main = co.wrap(function *() {
  return yield promisedOne();
});


// main function now returns promise
main().then(console.log);

This can often come handy when we want to use `co` with other libraries/frameworks which don’t support generator based workflow. For example, here’s a Gist that demonstrates how to use generators with the HapiJS web framework – https://gist.github.com/grabbou/ead3e217a5e445929f14. The route handlers are written using generator function and then adapted using `co.wrap` for Hapi.

Categories
NodeJS

Deploying a NodeJS 5 app with nginx on Ubuntu

In this blog post, we would follow the steps to deploy a NodeJS app using the latest version of Node with nginx on Ubuntu.

Installing Node.js 5

The official repository on Ubuntu doesn’t ship the latest version of NodeJS yet. So we will use a third party source to install it from:

curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -
sudo apt-get install -y nodejs

Using PM2

I love PM2 for keeping my node apps alive. If you didn’t know, PM2 is an awesome tool that launches Node processes and monitors them. If it crashes, it can restart them. PM2 is very easy to setup and use. It’s also quite feature packed.

We would setup PM2, launch our app with it and then generate a launch script so PM2 itself is started on system reboot.

npm install -g pm2 # Install PM2
pm2 start index.js # Start an app
pm2 startup ubuntu # Create a launch script for PM2

Nginx Configuration

Now that the app is running, it’s time to setup nginx as our reverse proxy. Here’s the default configurations I use:

server {
    listen 80;


    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
Categories
Javascript NodeJS

Live Debugging Webhooks with Ngrok

ngrok is an awesome service – it creates secure tunnels to localhost. With ngrok, you get a url like http://459387bb.ngrok.com which is actually tunnel to a port to your local machine. So any request you make to that url is served by the app that you run on that port.

I know there are many cool services to debug webhooks like Requestbin – but the main benefit of ngrok is the app keeps running on your app, serving live traffic. So you can debug it in real time.

In this blog post, we would use a Node.js server with ngrok to serve Mandrill webhook requests.

Installing ngrok

Downloading and installing ngrok is pretty easy as you can find here — https://ngrok.com/download. However, if you’re on OS X and use Homebrew, you can install it with just one command:

brew install ngrok

Creating a Node.js App

Here’s a sample Node app that listens on port 3000 and parses the mandrill payload using body-parser package.

"use strict";

//----> Require
var bodyParser = require("body-parser");
var express = require("express");

//----> Bootstrap
var app = express();

//----> Middlewares
app.use(bodyParser.urlencoded({
    extended: false
}));

//----> Routes

// Just a hello world
app.get("/", (req, res) => {
    res.send("Hello world!");
});

// Mandrill webhook
app.post("/webhooks/mandrill", (req, res) => {
    var payload = req.body['mandrill_events'];
    var events = JSON.parse(payload);

    events.forEach((item) => {
        var event = item['event'];
        var email = item['msg']['email'];
        var doc = {
            "event": event,
            "email": email
        };

        var json = JSON.stringify(doc);
        // Do some more processing

    });

    res.send("OK");
});


//----> Run the server
var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('App listening at http://%s:%s', host, port);
});

Tunneling Traffic

Once we have the app running on port 3K, we can ask ngrok to create a tunnel for us. For this we just need to pass the port number to the ngrok command:

ngrok 3000

We would get an url soon afterwards. We can use this url to POST requests. In our case, go to your Mandrill account and create a webhook. Mandrill will send events to this url and it will be served by your app, running locally on your machine. You can make changes to the codes and restart anytime.

Awesome, no?