3. WHO AM I?
DAN JENKINS
NODE.JS DEVELOPER / ARCHITECT
GOOGLE DEVELOPER EXPERT IN WEBRTC
LOVE LEGO & TECHNIC
GENERAL GEEK
FOUNDER OF NIMBLE APE LTD
❤ OPEN SOURCE
3
8. NODE.JS & I
STARTED WITH NODE.JS WHEN IT WAS A BABY - 0.4
BUILT MANY, MANY MICROSERVICES AND REST APIS WITH NODE
SPENTTHE PASTYEAR WORKING ON A PLATFORM CALLED RESPOKE - WEBRTC
8
10. WARNING…
SOME BAD PRACTICES ARE USED IN SOME OF THE EXAMPLES.
I KNOW YOU SHOULDN’T DO THESE THINGS.
BUT, ITS THE EASIEST WAYTO SHOW THE POINT IN THE SMALL CONFINES OF A
SLIDE DECK.
I PROMISE I KNOW WHAT I’M DOING…
10
12. WHO’S WRITTEN CODE LIKE THIS ?
12
createAdministrator: function (req, res) {
Administrators.create({some: data}, function cb(error, admin) {
if (error) {
console.error('Error creating Admin');
res.send(500)
return;
}
res.admin = admin;
doAnotherCall(res, function cb2(err2){
res.send(200, res.admin);
});
});
}
13. OR LIKE THIS
13
var http = require('http');
var uuid = require('uuid');
function respond(res) {
console.log('Got request with ID', res.id);
res.end('Response');
}
var server = http.createServer(function handleRequest(req, res){
res.id = uuid();
respond(res)
});
server.listen(8080, function(){
console.log("Server listening on: http://localhost:8080");
});
14. OR LIKE THIS
14
var http = require('http');
var uuid = require('uuid');
function doSomething(res, id) {
console.log('Do something with request with ID', id);
respond(res, id);
}
function respond(res, id) {
console.log('Responding to request with ID', id);
res.end('Response');
}
var server = http.createServer(function handleRequest(req, res){
var id = uuid();
doSomething(res, id);
});
server.listen(8080, function(){
console.log("Server listening on: http://localhost:8080");
});
26. “Continuation-local storage
works like thread-local storage in
threaded programming, but is
based on chains of Node-style
callbacks instead of threads.”
26
27. IT MEANS YOU CAN STOP DOING THIS…
27
var http = require('http');
var uuid = require('uuid');
function respond(res) {
console.log('Got request with ID', res.id);
res.end('Response');
}
var server = http.createServer(function handleRequest(req, res){
res.id = uuid();
respond(res);
});
server.listen(8080, function(){
console.log("Server listening on: http://localhost:8080");
});
28. AND START DOING THIS…
28
var http = require('http');
var uuid = require('uuid');
var createNamespace = require('continuation-local-storage').createNamespace;
var namespace = createNamespace('request-life');
function respond(res) {
console.log('Got request with ID', namespace.get('requestId'));
res.end('Response');
}
var server = http.createServer(function handleRequest(req, res){
namespace.set('requestId', uuid());
respond(res);
});
server.listen(8080, function(){
console.log('Server listening on: http://localhost:8080');
});
31. 1
31
var createNamespace = require('continuation-local-storage').createNamespace;
var session = createNamespace('my session');
var db = require('./lib/db.js');
function start(options, next) {
db.fetchUserById(options.id, function (error, user) {
if (error) return next(error);
session.set('user', user);
next();
});
}
32. 2
32
var getNamespace = require('continuation-local-storage').getNamespace;
var session = getNamespace('my session');
var render = require('./lib/render.js')
function finish(response) {
var user = session.get('user');
render({user: user}).pipe(response);
}
33. SO IT JUST WORKS?
I DON’T HAVE TO DO ANYTHING FUNKY?
44. 44
// Copyright (c) 2015. David M. Lee, II
'use strict';
var shimmer = require('shimmer');
// require mysql first; otherwise you can get some bizarre
// "object is not a function" errors if cls-mysql is loaded first.
require('mysql');
var Protocol = require('mysql/lib/protocol/Protocol');
var Pool = require('mysql/lib/Pool');
module.exports = function(ns) {
shimmer.wrap(Protocol.prototype, '_enqueue', function(enqueue) {
return function(sequence) {
sequence._callback = ns.bind(sequence._callback);
return enqueue.call(this, sequence);
};
});
shimmer.wrap(Pool.prototype, 'getConnection', function(getConnection) {
return function(cb) {
return getConnection.call(this, ns.bind(cb));
};
});
};
50. IT ALSO HAS A PERFORMANCE COST
THE MORE YOU HAVE,THE MORE YOU’LL IMPACTYOUR PERFORMANCE
COST IS AGAINST A NAMESPACE, NOT DATA IN THE NAMESPACE
KEEP THINGS TO A MINIMUM
50
52. IF YOU’RE DOING IT RIGHT…
YOU SHOULD BE USING SHRINKWRAP ANYWAY
(OR ANOTHER TECHNIQUE TO LOCK DEPENDENCIES)
SO BREAKAGES SHOULD BE LIMITED TO YOUR DEVELOPMENT ENVIRONMENT
WHICH MEANS MOAR BONUS FOR LITTLE TO NO RISK
VERY LOW PERFORMANCE COST
52
54. MOST EXAMPLES WERE TAKEN FROM
https://github.com/othiym23/node-continuation-local-storage
https://github.com/othiym23/shimmer
https://github.com/building5/cls-mysql
54