Matthew Eernisse, NodeJs, .toster {webdev}

38
Intro to NodeJS Matthew Eernisse Toster Conference 2011-10-28 2001

Transcript of Matthew Eernisse, NodeJs, .toster {webdev}

Page 1: Matthew Eernisse, NodeJs, .toster {webdev}

Intro to NodeJSMatthew Eernisse

Toster Conference 2011-10-282001

Page 2: Matthew Eernisse, NodeJs, .toster {webdev}

Who am I?

Matthew EernisseWork at Yammer@mde on Twitter

Page 3: Matthew Eernisse, NodeJs, .toster {webdev}

JavaScript at YammerBrowsers (yammer.com Web UI)

Adobe AIR Desktop

V8 in Rails via TheRubyRacer

NodeJS

Page 4: Matthew Eernisse, NodeJs, .toster {webdev}

NodeJS:“Evented I/O for V8 JavaScript”

http://nodejs.org/

Page 5: Matthew Eernisse, NodeJs, .toster {webdev}

var http = require('http');

http.createServer(function (req, res) {

res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');

}).listen(1337, "127.0.0.1");

console.log( 'Server running at http://127.0.0.1:1337/');

Hello, NodeJS

Page 6: Matthew Eernisse, NodeJs, .toster {webdev}

Server JS

Page 7: Matthew Eernisse, NodeJs, .toster {webdev}

Netscape Enterprise Server (OG SSJS)

Microsoft IIS

Helma (now RingoJS)

Whitebeam

Zimki

Jaxer

Perservere

Nitro

Google App Engine

CouchDB

NodeJS

History of SSJS

Page 8: Matthew Eernisse, NodeJs, .toster {webdev}

Why NodeJS now?Steve Yegge’s NBL post, 2007-02-10

Competition in JavaScriptinterpreters

Simple, POSIX API

Non-blocking from the ground up; soare the libraries

Page 9: Matthew Eernisse, NodeJs, .toster {webdev}

What is NodeJS good for?Lightweight, networked apps

Proxies with embedded logic

Streaming data

System scripting

Evented realtime apps

•••••

Page 10: Matthew Eernisse, NodeJs, .toster {webdev}

NodeJS is not good at complexdatabase-backed Web

applications.You can use Rails.

Page 11: Matthew Eernisse, NodeJs, .toster {webdev}

Geddy Web framework:https://github.com/mde/geddy

Page 12: Matthew Eernisse, NodeJs, .toster {webdev}

NodeJS at YammerDevelopment proxy

Jake for build and test(https://github.com/mde/jake)

Upload service for files and images (Geddy v0.2)

Browserless tests with FooUnit (https://github.com/foobarfighter/foounit)

Realtime, collaborative document-editing service

Page 13: Matthew Eernisse, NodeJs, .toster {webdev}

Jake build toolhttps://github.com/mde/jake•

Similar to Make or Rake

Tasks, prerequisites

File tasks, directory tasks

Namespaces

PackageTasks

Async task execution

Just executable JavaScript

Page 14: Matthew Eernisse, NodeJs, .toster {webdev}

desc('This is the default task.');task('default', function () { console.log('This is the default task.'); console.dir(arguments);});

namespace('foo', function () { desc('This the foo:bar task'); task('bar', function () { console.log('doing foo:bar task'); console.dir(arguments); });

desc('This the foo:baz task'); task('baz', ['default', 'foo:bar'], function () { console.log('doing foo:baz task'); console.dir(arguments); });

});

Page 15: Matthew Eernisse, NodeJs, .toster {webdev}

desc('This is an asynchronous task.');task('async', function () { setTimeout(function () { console.log('Hooray!'); complete(); }, 1000);}, true);

desc('Calls the foo:bar task and its dependencies.');task('invokeFooBar', function () { // Calls foo:bar and its deps jake.Task['foo:bar'].invoke(); // Does nothing jake.Task['foo:bar'].invoke(); // Only re-runs foo:bar, but not its dependencies jake.Task['foo:bar'].reenable(); jake.Task['foo:bar'].invoke();});

Page 16: Matthew Eernisse, NodeJs, .toster {webdev}

var fs = require('fs') , pkg = JSON.parse( fs.readFileSync('package.json').toString()) , version = pkg.version

var t = new jake.PackageTask('jake', 'v' + version, function () { var fileList = [ 'Makefile' , 'Jakefile' , 'README.md' , 'package.json' , 'lib/*' , 'bin/*' , 'tests/*' ]; this.packageFiles.include(fileList); this.needTarGz = true; this.needTarBz2 = true;});

Page 17: Matthew Eernisse, NodeJs, .toster {webdev}

Remote upload serviceMinimal v1 in prod, Nov. 2010

Redis, CORS XHR-push or JSONP for upload-progressreporting

Onboard thumbnailing, remote services for video anddocument post-processing

Three-machine cluster, not under a heavy load

Large file sizes (e.g., 1.5GB)

Page 18: Matthew Eernisse, NodeJs, .toster {webdev}

Realtime, collaborative doc-editing service

In beta Oct. 21, 2011 (last week)

NodeJS, Socket.io, PostgreSQL

No production metrics yet for perf/scalability

Page 19: Matthew Eernisse, NodeJs, .toster {webdev}

Coding JS for Node

Page 20: Matthew Eernisse, NodeJs, .toster {webdev}

Awesome:JavaScript is simple and

super-flexible

Page 21: Matthew Eernisse, NodeJs, .toster {webdev}

Horrible:JavaScript is simple and

super-flexible

Page 22: Matthew Eernisse, NodeJs, .toster {webdev}

Even shelling out is async?

“1, 3, 2, go!” development

Evented and callback-based control-flow

A familiar model?

Async patterns and libraries

•••••

Asynchronous code

Page 23: Matthew Eernisse, NodeJs, .toster {webdev}

var asyncFun = function () { console.log('1'); setTimeout(function () { console.log('3'); }, 0); console.log('2'); console.log('go!');};

1, 3, 2, go!

Page 24: Matthew Eernisse, NodeJs, .toster {webdev}

var fetchAndUpdate = function (params) { var items = db.fetch(someQuery); for (var i = 0, ii = items.length; i++) { item.update(params); } return true;};

Sync fetch-and-update

Page 25: Matthew Eernisse, NodeJs, .toster {webdev}

var fetchAndUpdate = function (params, callback) { db.fetch(someQuery, function (items) { var count = 0; for (var i = 0, ii = items.length; i++) { item.update(params, function () { count++; if (count == ii) { callback(true); } }); } });};

Async fetch-and-update

Page 26: Matthew Eernisse, NodeJs, .toster {webdev}

jQuery.ajax({ url: '/foo/bar.json', success: function () { alert('yay!'); }});

jQuery('#foo').bind('click', function (e) { // Do some stuff});

Is this familiar?

Page 27: Matthew Eernisse, NodeJs, .toster {webdev}

Async patterns and libs

Queue

Promise/deferred

In-flight registry

•••

Page 28: Matthew Eernisse, NodeJs, .toster {webdev}

var asyncQueueHandler = function (items, handler, callback) { var queue = items.slice() , handleNextItem = function () { var next = queue.pop(); if (next) { handler(next, function () { handleNextItem(); }); } else { callback(); } }; handleNextItem();};

Queue

Page 29: Matthew Eernisse, NodeJs, .toster {webdev}

var p = new yammer.util.Promise();p.when('foo', 'bar', 'baz').then( function () { console.log('done!');});p.satisfy('foo');p.satisfy('bar');p.satisfy('baz');

p.then(function () { console.log('still done!');});

Promise

Page 30: Matthew Eernisse, NodeJs, .toster {webdev}

NodeJS in production

Page 31: Matthew Eernisse, NodeJs, .toster {webdev}

Third-party modules still may changerapidly

Maintain forks, push back patches whereappropriate

App dependencies

Page 32: Matthew Eernisse, NodeJs, .toster {webdev}

Callbacks in global scope have no stack

Assume you’re fucked

Default condition is a preemptible error

In-flight registry with uncaughtExceptionhandler

••••

Debugging NodeJS

Page 33: Matthew Eernisse, NodeJs, .toster {webdev}

FlightCheckhttps://github.com/mde/flight_check•

Add items to in-flight registry

Per-item timeout

Configurable polling-interval

Define a timeout-handler

Page 34: Matthew Eernisse, NodeJs, .toster {webdev}

var FlightCheck = require('flight_check').FlightCheck;var handler = function (req, resp) { var checker = new FlightCheck(function (key) { resp.writeHead(500); resp.end('Oops, something bad happened.'); }); checker.add('foo', 10000); doFoo(req, function (result) { if (result.ok) { checker.clear('foo'); // Do some other stuff resp.writeHead(200); resp.end('Hooray!'); } });};

process.on('uncaughtException', function (err) { // Do some kind of logging});

In-flight registry

Page 35: Matthew Eernisse, NodeJs, .toster {webdev}

Measure everything

Log everything

https://github.com/mikejihbe/metrics

•••

Visibility, metrics

Page 36: Matthew Eernisse, NodeJs, .toster {webdev}

Communicative, consultative dev

Ask what is expected

Play nicely with others

•••

Ops

Page 37: Matthew Eernisse, NodeJs, .toster {webdev}

The future?JS interpreters will keep improving

JS language will keep improving (see:JS.next)

NodeJS ecosystem will grow and mature

Try NodeJS, you’ll like it

••

••

Page 38: Matthew Eernisse, NodeJs, .toster {webdev}

Matthew Eernissehttp://twitter.com/mde

Yammer Developer Centerhttp://developer.yammer.com/