Kotan Code 枯淡コード

In search of simple, elegant code

Menu Close

Tag: javascript

Debugging Node.js Applications in Cloud Foundry

I just added a post over on Medium describing some steps we took to do remote debugging of a Node.js application running in Cloud Foundry.

Check out the post here: https://medium.com/@KevinHoffman/debugging-node-js-applications-in-cloud-foundry-b8fee5178a09#.dblflhdxm

 

 

Real-Time Selfie Stick Destruction Monitoring Console

I recently stumbled upon a library that made me happy in so many ways. First, you can use this library to quickly create all kinds of dashboards that can be used for a number of purposes, not the least of which is real-time monitoring of systems or system data. This library is blessed-contrib, and since it uses ASCII/ANSI art to make these dashboards available in the terminal window, it brings back so many great memories of the “good old days”, I had to try it out.

Every time I play with some new library or technology, I need to come up with some hypothetical sample use case. In this case, I wondered what it would look like if I could monitor the real-time per-capita density of people wielding selfie-sticks. This would guide my decision as to where to deploy a selfie-stick-interfering EMP device.

This is what such a dashboard would look like:

Selfie Stick Density Monitoring

Selfie Stick Density Monitoring

I would be lying if I said that looking at this didn’t make me want to fire up my copy of War Games and play a game of Global Thermonuclear War with Joshua.

And here’s the ridiculously simple JavaScript code, executed by Node.js:

var blessed = require('blessed')
 , contrib = require('../')
 , screen = blessed.screen()
 , map = contrib.map({label: 'Selfie Stick Destruction Console'})

screen.append(map)
map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: "red", char: "X" })
map.addMarker({"lon" : "13.25", "lat": "52.30", color: "red", char: "X" })
map.addMarker({"lon" : "72.82", "lat": "18.96", color: "yellow", char: "X" })
map.addMarker({"lon" : "103.85", "lat": "1.3", color: "white", char: "X" })
map.addMarker({"lon" : "116.4", "lat" : "39.93", color: "red", char: "X" })
map.addMarker({"lon" : "-0.1", "lat" : "51.52", color: "red", char: "X" })
map.addMarker({"lon" : "-118.41", "lat" : "34.11", color: "red", char: "X" })

screen.render()

This just scratches the surface, but the big lesson learned here is this: I love the internet, because it brings me things like this. I will now absolutely use this to create a terminal-based monitoring tool for the next application I build, regardless of domain or complexity 🙂

Tracking the Zombie Apocalypse with the MEAN Stack – Pt I

When some hardware folks find a new device, they ask, “Will it blend?” When I find a new programming language, stack, or platform, I ask, “Can it help me survive the impending zombie apocalypse?”

Today I started working with the MEAN (MongoDB, Express, AngularJS, Node.js) stack. Much like LAMP (Linux, Apache, MySQL, PHP) was “back in the day”, developers using one or more of these technologies naturally gravitate to this particular combination. This combination happens so often that several folks have already done some work toward providing a useful abstraction layer on top of this stack.

In my case, I started working with mean.io‘s stack, which aims to provide a rails-y command-line based interface to building MEAN web applications in full-stack JavaScript.

I won’t go through the details of installing and configuring the Mean IO tools – their website does a pretty good job of getting you set up. Before I get to my code sample, here’s a quick recap of the components of the MEAN stack:

  • MongoDB – This is a document-oriented database that works really well as an all-purpose NoSQL store, but it also has some really powerful capabilities that make it a good choice for even some of the most strict performance requirements.
  • Express – This is a very fast, lightweight web application framework that sits on top of Node.js
  • AngularJS – This is an extremely powerful, very popular framework for building “application in a page” type client-side code for web applications.
  • Node.js – This is a low-level framework that allows you to run JavaScript on the server. On its own, Node.js is not a web application server, it is just the framework that enables such servers.

Now on to my sample. I want to build a web application that will help me monitor the zombie outbreaks that will inevitably start happening all over the world. This sounds like an ideal, simple CRUD example I can use to test out the MEAN stack.

First, I created a new application using the mean command line, then I created a new package (reusable sub-module of a web application, mean.io actually has a store-like interface for sharing these packages) called apocalypse with the command line “mean package apocalypse”.

The package has two really important directories: public and server. The public directory is the client-side directory, where all your AngularJS code and HTML templates will go. The server directory is the server-side directory which is processed by Node and Express.

This blog post will go through the server side and then in the next post, I’ll go through the client side.

In the server directory, there are a number of other directories, including controllersmodelsroutes, and tests. I’m going to leave tests out and start with a model. Since this is a server-side model, we’re actually talking about an object that interacts with MongoDB via mongoose.

Let’s take a look at my OutbreakReport model, which represents an instance of a report of a zombie outbreak – a description, a geocoordinate, and a count of the number of observed zombies.

'use strict';
/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
 Schema = mongoose.Schema;
/**
 * Outbreak Report Schema
 */
var OutbreakReportSchema = new Schema({
 created: {
   type: Date,
   default: Date.now
 },
 title: {
   type: String,
   required: true,
   trim: true
 },
 zombieCount: {
   type: Number,
   default: 0
 },
 latitude: Number,
 longitude: Number,
 user: {
   type: Schema.ObjectId,
   ref: 'User'
 },
 updated: {
   type: Array
 }
});
OutbreakReportSchema.path('title').validate(function(title) {
 return !!title;
}, 'Title cannot be blank');
/**
 * Statics
 */
OutbreakReportSchema.statics.load = function(id, cb) {
 this.findOne({
 _id: id
 }).populate('user', 'name username').exec(cb);
};
mongoose.model('OutbreakReport', OutbreakReportSchema);

The schema is a JavaScript object that represents a mongoose schema type, which will be used to constrain the objects that go into and come out of MongoDB. If this code looks like the articles sample that comes with the mean.io scaffolding, that’s not a coincidence. I’m diving into a new technology, so I’m reusing as much sample code as I can to avoid making stupid mistakes.

Now that I have a model, I need a controller to sit on top of it. This controller is run on the server, and serves as the plumbing that supports the RESTful API for dealing with outbreak reports programmatically. It can either supply a client application with a zombie outbreak backend, or (as you’ll see in the next post), it can also supply an AngularJS front-end with all the data interaction necessary to manipulate this domain.

'use strict';
/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
 OutbreakReport = mongoose.model('OutbreakReport'),
 _ = require('lodash');
module.exports = function(OutbreakReports) {
return {
 /**
 * Find outbreak report by id
 */
 outbreakreport: function(req, res, next, id) {
   OutbreakReport.load(id, function(err, report) {
     if (err) return next(err);
     if (!report) return next(new Error('Failed to load outbreak report ' + id));
     req.outbreakreport = report;
     next();
   });
 },
 /**
 * Create an outbreak report
 */
 create: function(req, res) {
   var report = new OutbreakReport(req.body);
   report.user = req.user;
   report.save(function(err) {
     if (err) {
        return res.status(500).json({
        error: 'Cannot save the outbreak report'
 });
 }
 OutbreakReports.events.publish('create', {
 description: req.user.name + ' created ' + req.body.title + ' outbreak report.'
 });
res.json(report);
 });
 },

 /**
 * Update an outbreak report
 */
 update: function(req, res) {
   var report = req.outbreakreport;
   report = _.extend(report, req.body);
   report.save(function(err) {
     if (err) {
       return res.status(500).json({
         error: 'Cannot update the outbreak report'
       });
 }
 OutbreakReports.events.publish('update', {
 description: req.user.name + ' updated ' + req.body.title + ' outbreak report.'
 });
res.json(report);
 });
 },

 /**
 * Delete an outbreak report
 */
 destroy: function(req, res) {
 var report = req.outbreakreport;
 report.remove(function(err) {
 if (err) {
   return res.status(500).json({
   error: 'Cannot delete the report'
 });
 }
 OutbreakReports.events.publish('remove', {
 description: req.user.name + ' deleted ' + report.title + ' outbreak report.'
 });
  res.json(report);
 });
 },

/**
 * Show an outbreak report
 */
 show: function(req, res) {
   OutbreakReports.events.publish('view', {
   description: req.user.name + ' read ' + req.outbreakreport.title + ' outbreak report.'
 });
res.json(req.outbreakreport);
 },

 /**
 * List of Reports
 */
 all: function(req, res) {
   OutbreakReport.find().sort('-created').populate('user', 'name username').exec(function(err, reports) {
 if (err) {
   return res.status(500).json({
   error: 'Cannot list the outbreak reports'
 });
 }
res.json(reports);
 });
 }
 };
}

Those of you who have spent any amount of time building web applications, regardless of platform, should start to recognize what’s happening here. We’ve got a controller to invoke the right code to load or manipulate domain objects (in this case, OutbreakReports), and we’ve got a domain object that is linked to a MongoDB backing store. Now we need to define the routes, which define the RESTful API used to interact with OutbreakReports:

'use strict';
/* jshint -W098 */
// The Package is past automatically as first parameter
module.exports = function(OutbreakReports, app, auth, database) {

var reports = require('../controllers/outbreakreports')(OutbreakReports);

app.route('/api/outbreakreports')
.get(reports.all)
.post(auth.requiresLogin, reports.create);
app.route('/api/outbreakreports/:reportId')
.get(auth.isMongoId, reports.show)
.put(auth.isMongoId, auth.requiresLogin, reports.update)
.delete(auth.isMongoId, auth.requiresLogin, reports.destroy);

// Finish with setting up the articleId param
app.param('reportId', reports.outbreakreport);
};

Now, if I’ve done everything right, I should be able to issue a curl against http://localhost:3000/api/outbreakreports and get some data (I went into my MongoDB instance and manually created the outbreak reports collection and an initial document since I don’t yet have a GUI).

vertex5:zombies kevin$ curl http://localhost:3000/api/outbreakreports
[{"_id":"5573098f83b289c40d15c229","title":"random mob","latitude":41.8596,"longitude":72.6791,"user":{"name":"Kevin Hoffman","username":"kotancode","_id":"5572cdae31b741c910b11c15"},"updated":[],"zombieCount":3,"created":"2015-06-06T10:56:03.803Z"}]

From start to finish, from empty directory to working prototype, I think it took me 20 minutes, and most of that time was just the effort of typing things in. This is, of course, the value add of scaffolding to begin with. I’m quite certain it would have taken me a lot longer to do anything more complicated, but I am really pleased with how smoothly everything ran the first time.

In the next post, I’ll cover how to create the AngularJS GUI to consume the outbreak reports model, which will include creating a service, an Angular controller, HTML, etc. Stay tuned!

Using WebSockets with Play Framework 2.1.0

As odd as this may seem to some of you, I have been creating an enterprise web application using the Play Framework and the full typesafe stack, including Scala and Akka. It doesn’t surprise me, however, as the experience I have been having with this stack is quite possibly one of the most productive experiences I’ve had with any web dev stack, open source or commercial.

To get right to the chase – this web application allows multiple users to edit the same entity (which I am calling documents for now) at the same time. I’ve already got the optimistic concurrency thing taken care of (e.g. you can’t commit your changes over top of someone else’s changes). What I wanted to make things even cooler was to push a “toast” (a fade-in-fade-out notification dialog) to the user if they are currently looking at a page that was just modified by someone else.

The solution? WebSockets. I decided I would create a news feed of edits and then each page can decide if it wants to use that socket to be made aware of notifications. The JavaScript on that page decides if the notification is relevant (e.g. the edit news item is for that current document). To do this, I adapted the Play Framework sample websockets-chat to serve as a document edit news feed. Users join the feed when the page decides it needs that feed (for push or pull or both), and they quit when the page goes away (if you navigate away from a page that had a JavaScript-initiated websocket connection, the connection dies and the chatroom-based code considers that a Quit).

So, here’s the code for my WebSocket controller, which will control all of the feeds for my site:

object WebSockets extends Controller {
    def editFeed(user:String) = WebSocket.async[JsValue] { request =>
        ChangeFeed.join(user)
    }
}

And here’s the code for the ChangeFeed actor class and it’s companion object. This code should look ridiculously familiar, since it’s basically the chatroom example. All I’ve really done is replace the Talk case class with my PostUpdate case class, which contains information about the type of document being updated and the document name. This information is enough for the individual pages to decide whether they need to display these push notifications.

// imports cut for brevity..
object ChangeFeed {
   implicit val timeout = Timeout(1 second)

   lazy val default = {
     val feedActor = Akka.system.actorOf(Props[ChangeFeed])
     // -- this is where the chatroom robot used to get initialized...
     feedActor
   }

   def join(username:String): scala.concurrent.Future[Iteratee[JsValue,_],Enumerator[JsValue])] = {
   ( default ? Join(username)).map {
     case Connected(enumerator) =>
       val iteratee = Iteratee.foreach[JsValue] { event =>
          default ! PostUpdate(username, (event \ "docType").as[String], (event \ "docName").as[String])
       }.mapDone { _ =>
          default ! Quit(username) // this quits the channel when the web page goes away
       }
       (iteratee, enumerator)
    case CannotConnect(error) => // .. handle error (snipped for brevity)
   }
   }
}

// The chatroom only allows one username per socket, on a website,
// my users could have multiple tabs open to the same site, so I let them
// open new sockets even if the username is the same.
class ChangeFeed extends Actor {
    val members = Set.empty[String]
    val (feedEnumerator, feedChannel) = Concurrent.broadcast[JsValue]

   def receive = {
     case Join(username) => {
         // yes, I know there's a more idiomatic scala way to do this
         if (!members.contains(username)) {
             members = members + username
         }
         sender ! Connected(feedEnumerator)
         self ! NotifyJoin(username)
      }
     case NotifyJoin(username) => {
        notifyAll("join", username, "", "")
     }
     case PostUpdate(username, docType, docName) => {
        notifyAll("update", username, docType, docName)
     }
     case Quit(username) => {
        members = members - username
        notifyAll("quit", username, "", "")
     }
   }

   def notifyAll(kind: String, user:String, docType: String, docName: String) {
     val msg = JsObject(
         Seq(
            "kind" -> JsString(kind),
            "user" -> JsString(user),
            "docType" -> JsString(docType),
            "docName" -> JsString(docName),
            "members" -> JsArray(members.toList.map(JsString))
         )
     )
   }
}

// case classes snipped for brevity

Once I’ve got a controller that can ask an Actor for a socket and dispense it accordingly, then the only thing left for me to do is create some client-side JavaScript that accesses my web socket and there are plenty of examples of doing that on the web. The one piece of this that makes things even nicer in Play is that I can automatically get the websocket URL from a controller route:

var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var feedSocket = new WS(@"routes.WebSockets.editFeed.webSocketURL()")

This automatically gives me a URL that looks like ws://server/websockets/editFeed.

All I can say is that so far, using Play to build an enterprise web application has been an absolute joy and, having been able to create this websocket-based “edit feed” infrastructure in just a few hours was absolutely amazing.