Prototyping with Node.js

My use of the word prototype, is not the function, but rather the concept.  One of my IT mentors taught me that prototyping an application is extremely useful. That is to say, to quickly create a functioning application in some scripting language.  Then, if the app’s logic is sound, one can transition it to a different language if needed.

Node.js

In my current situation, I had a tool I wrote in Grails, that was giving me some memory issues.  I’ve come to the conclusion my app has too many objects being created unnecessarily.  I also think that the threads are an issue for the app to handle.

Seeing many areas of improvement in the services, logic, domain models, etc., I decided to rewrite the app.  But I didn’t want to rewrite it in Grails from the start. I wanted to prototype it out and see if I could quickly get different ideas running and how they would function differently than what I had previously done.  In other words, I didn’t want to create a full Grails app with Tomcat, etc.

I choose Node.js as a prototype because it’s Grails-ish.  Certainly it’s not “Grails” but it has that same Java vibe, but it’s quick and easy to get ideas up and running.

Express.js

With the Express.js framework, I am able to create the MVC type of design of the project.  If desired it can generate code, but I’m not going in that direction. I’m trying to lock down functionality and create by hand, rather than creating unnecessary tasks that won’t be utilized via a generator.

Node-Crontab

This is the core of my tool.  In Grails I used a plugin called Quartz.  In Node.js I’m using a plugin called Node-Crontab.  They work exactly the same.  This queues up jobs that call methods, which perform a production task and save the result to a database.

MongoDB

Since Node.js is usually used with Mongo, I decided this was a good time to try and make use of it.

Redis

Redis may have use later, I have it on my list, but if it’s unnecessary for this project, I’ll scratch it off.

Mongoose

Mongoose is probably the most utilized plugin I’m using (after Express), as it offers me the ORM style of saving and retrieving data.  For example, data can be saved like so:

var TestResults = mongoose.model('test_results', TestResultsSchema);

// Saving results to MongoDB
var result = new TestResults({
    testType: type,
    dnis: dnis,
    server: server,
    result: code,
    date: Date.now()
});
result.save(function (err) {if (!err) {console.log ('Successful Save!')}
else{console.log(err)}

At the end of my first day using Node.js, I had reproduced the core logic in the primary tool.  The tool calls a series of phone numbers and performs various tests to validate call completion.  I’ve successfully got the logic behind 2 of the 3 main hurdles.

Refactor Results

The codebase is so far a lot smaller, mainly because I’m making it more re-usable and using more logical choices of methods and domain models that extend better.

In my Grails app, I later knew I had an issue where each “test” I was performing was using it’s own services, domain model and quartz jobs.  Now that I know better, I’ve prototyped out a solution in Node.js where:

  • One domain model is used
  • No services needed
  • One Quartz/Cron class used, each job is a method from that class
  • One phone call Class was created, with one method to pass params for each test type.

So far I’ve refactored the code to go from using 10 services in Grails, to 1 class handling a more robust method call, that can accommodate the majority of sip calls executed.

Whats Left

I still need to add in:

  • Business logic (how many times to retry a call before marking it a failure, etc.)
  • E-mail results when a threshold has been breached (and email “fixed” messages when the error state is no longer error.
  • Add in the non-sip related functionality.
  • Create a similar UI – but work with the web socket model to better display data on screen (rather than my 5min refresh I was using in the original tool.)  The UI needs to display the data in a very specific way. All results will be in a table, showing the current state and a count of how many times this particular event failed over 1hr, 3hr, 6hr, etc.
  • (new functionality) consider making the app networked – meaning there is a server aspect that displays the results from the database.  Slave sessions will run on other physical servers and save the results to the db.

End Game

When I’m complete I will stand the Node.js/Express app up someplace and check it’s performance.  I’ll roll the changes from the prototype into the Grails app and then compare the performance of the two instances.

I have a feeling Node.js might be a good choice for this project in it’s finality… mainly due to the single thread non-blocking I/O… My app itself should not be CPU heavy… so it really shouldn’t require multiple threads.  The fact it’s using multiple threads now in Grails, is a concern for me and why I think it might be over-consuming RAM and needing regular restarts of Tomcat.

But we’ll see.  Perhaps the app is more CPU intensive than I imagine, and perhaps I’ll need Grails to support the many sip-call tests I’m running each hour.

Prototyping with Node.js
User Rating: 0 (0 votes)