Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
BRINGING CHAOS TO ORDER
IN YOUR NODE.JS APP
DAN JENKINS
NIMBLE APE
https://nimblea.pe
WHO AM I?
WHO AM I?
DAN JENKINS
NODE.JS DEVELOPER / ARCHITECT
GOOGLE DEVELOPER EXPERT IN WEBRTC
LOVE LEGO & TECHNIC
GENERAL GEEK
FOU...
4
/danjenkins
5
@dan_jenkins
6
nimblea.pe | @nimbleapeltd
NODE.JS & I
STARTED WITH NODE.JS WHEN IT WAS A BABY - 0.4
BUILT MANY, MANY MICROSERVICES AND REST APIS WITH NODE
SPENTTHE ...
FUNNY STORY…
9
H E L L O
my name is
Dan
G O O G L E I / O
WARNING…
SOME BAD PRACTICES ARE USED IN SOME OF THE EXAMPLES.
I KNOW YOU SHOULDN’T DO THESE THINGS.
BUT, ITS THE EASIEST W...
NODE.JS APPS CAN GET
IN A REAL MESS…
WHO’S WRITTEN CODE LIKE THIS ?
12
createAdministrator: function (req, res) {
Administrators.create({some: data}, function ...
OR LIKE THIS
13
var http = require('http');
var uuid = require('uuid');
function respond(res) {
console.log('Got request w...
OR LIKE THIS
14
var http = require('http');
var uuid = require('uuid');
function doSomething(res, id) {
console.log('Do so...
EVERYONE HAS AT SOME POINT…
DON’T TRY AND DENY IT…
WHAT PROBLEM ARE WE
TRYING TO SOLVE?
PASSING DATA AROUND TO OTHER
FUNCTIONS FOR USE LATER
19
req.id = ‘foo’;
console.log(req.id);
FOR EXAMPLE, SERVICE
BASED LOGGING
21
ASSIGN A REQUEST ID HERE
AND HAVE IT SENT ON TO ALL
OTHER SERVICES
WHICH MEANS ALLYOUR LOGS FROM ALLYOUR SERVICES ALLTI...
WHAT’S THE ANSWER?
23
OBVIOUSLY…
CLS
NODE-CONTINUATION-LOCAL-STORAGE
USERLAND MODULE
UTILISES ASYNC-LISTENER
24
/othiym23/node-continuation-local-storage
/...
IT HAS NOTHING TO DO WITH
LOCAL-STORAGE IN THE BROWSER
“Continuation-local storage
works like thread-local storage in
threaded programming, but is
based on chains of Node-style
...
IT MEANS YOU CAN STOP DOING THIS…
27
var http = require('http');
var uuid = require('uuid');
function respond(res) {
conso...
AND START DOING THIS…
28
var http = require('http');
var uuid = require('uuid');
var createNamespace = require('continuati...
IT’S MORE IMPRESSIVE THAN IT
LOOKS IN THIS SIMPLE EXAMPLE
I PROMISE
THAT’S AWESOME!
WHAT DO I NEED TO DO?
1
31
var createNamespace = require('continuation-local-storage').createNamespace;
var session = createNamespace('my sessio...
2
32
var getNamespace = require('continuation-local-storage').getNamespace;
var session = getNamespace('my session');
var ...
SO IT JUST WORKS?
I DON’T HAVE TO DO ANYTHING FUNKY?
KINDA…
BEWARE NATIVE INTERACTIONS
ANYTHING THAT TOUCHES NATIVE
CODE; YOU’LL NEED TO SHIM
SHIM ALL THE THINGS
/package/shimmer
/othiym23/shimmer
39
var http = require('http');
var shimmer = require('shimmer');
shimmer.wrap(http, 'request', function (original) {
retur...
OR USE AN EXISTING ONE
41
require('cls-mysql')(ns);
require('cls-redis')(ns);
require('cls-q')(ns);
require('cls-bluebird')(ns);
require('cls-es6...
42
YOU NEED TO BE WARY!
44
// Copyright (c) 2015. David M. Lee, II
'use strict';
var shimmer = require('shimmer');
// require mysql first; otherwi...
YOU HAVE TO KNOW WHAT
TO SHIM!
AND BEWARE THE INTERNALS
OF THE MODULE CHANGING
AN INTERNAL
MODULE CHANGE !== A PUBLIC API
CHANGE
WHICH MEANS YOU COULD BE
HIT BY A MINOR VERSION BUMP
WHICH COULD RESULT IN A
FAILING APPLICATION
IT ALSO HAS A PERFORMANCE COST
THE MORE YOU HAVE,THE MORE YOU’LL IMPACTYOUR PERFORMANCE
COST IS AGAINST A NAMESPACE, NOT D...
SO WHY USE IT?
IF YOU’RE DOING IT RIGHT…
YOU SHOULD BE USING SHRINKWRAP ANYWAY
(OR ANOTHER TECHNIQUE TO LOCK DEPENDENCIES)
SO BREAKAGES S...
THANKS!
DAN JENKINS
@dan_jenkins
MOST EXAMPLES WERE TAKEN FROM
https://github.com/othiym23/node-continuation-local-storage
https://github.com/othiym23/shim...
Bringing choas to order in your node.js app
You’ve finished this document.
Download and read it offline.
Upcoming SlideShare
Future of Web Apps - Giving Customer Support using WebRTC
Next
Upcoming SlideShare
Future of Web Apps - Giving Customer Support using WebRTC
Next
Download to read offline and view in fullscreen.

8

Share

Bringing choas to order in your node.js app

Download to read offline

Bringing Chaos to order in your node.js app - talk delivered at Node.js Dublin Meetup - talks about the CLS module.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Bringing choas to order in your node.js app

  1. 1. BRINGING CHAOS TO ORDER IN YOUR NODE.JS APP DAN JENKINS NIMBLE APE https://nimblea.pe
  2. 2. WHO AM I?
  3. 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
  4. 4. 4 /danjenkins
  5. 5. 5 @dan_jenkins
  6. 6. 6 nimblea.pe | @nimbleapeltd
  7. 7. 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
  8. 8. FUNNY STORY… 9 H E L L O my name is Dan G O O G L E I / O
  9. 9. 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
  10. 10. NODE.JS APPS CAN GET IN A REAL MESS…
  11. 11. 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); }); }); }
  12. 12. 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"); });
  13. 13. 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"); });
  14. 14. EVERYONE HAS AT SOME POINT…
  15. 15. DON’T TRY AND DENY IT…
  16. 16. WHAT PROBLEM ARE WE TRYING TO SOLVE?
  17. 17. PASSING DATA AROUND TO OTHER FUNCTIONS FOR USE LATER
  18. 18. 19 req.id = ‘foo’; console.log(req.id);
  19. 19. FOR EXAMPLE, SERVICE BASED LOGGING
  20. 20. 21 ASSIGN A REQUEST ID HERE AND HAVE IT SENT ON TO ALL OTHER SERVICES WHICH MEANS ALLYOUR LOGS FROM ALLYOUR SERVICES ALLTIE TOGETHER
  21. 21. WHAT’S THE ANSWER?
  22. 22. 23 OBVIOUSLY…
  23. 23. CLS NODE-CONTINUATION-LOCAL-STORAGE USERLAND MODULE UTILISES ASYNC-LISTENER 24 /othiym23/node-continuation-local-storage / continuation-local-storage /package/async-listener
  24. 24. IT HAS NOTHING TO DO WITH LOCAL-STORAGE IN THE BROWSER
  25. 25. “Continuation-local storage works like thread-local storage in threaded programming, but is based on chains of Node-style callbacks instead of threads.” 26
  26. 26. 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"); });
  27. 27. 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'); });
  28. 28. IT’S MORE IMPRESSIVE THAN IT LOOKS IN THIS SIMPLE EXAMPLE I PROMISE
  29. 29. THAT’S AWESOME! WHAT DO I NEED TO DO?
  30. 30. 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(); }); }
  31. 31. 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); }
  32. 32. SO IT JUST WORKS? I DON’T HAVE TO DO ANYTHING FUNKY?
  33. 33. KINDA…
  34. 34. BEWARE NATIVE INTERACTIONS
  35. 35. ANYTHING THAT TOUCHES NATIVE CODE; YOU’LL NEED TO SHIM
  36. 36. SHIM ALL THE THINGS
  37. 37. /package/shimmer /othiym23/shimmer
  38. 38. 39 var http = require('http'); var shimmer = require('shimmer'); shimmer.wrap(http, 'request', function (original) { return function () { console.log("Starting request!"); var returned = original.apply(this, arguments) console.log("Done setting up request -- OH YEAH!"); return returned; }; });
  39. 39. OR USE AN EXISTING ONE
  40. 40. 41 require('cls-mysql')(ns); require('cls-redis')(ns); require('cls-q')(ns); require('cls-bluebird')(ns); require('cls-es6-promise')(ns); require('cls-bcrypt')(ns);
  41. 41. 42
  42. 42. YOU NEED TO BE WARY!
  43. 43. 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)); }; }); };
  44. 44. YOU HAVE TO KNOW WHAT TO SHIM!
  45. 45. AND BEWARE THE INTERNALS OF THE MODULE CHANGING
  46. 46. AN INTERNAL MODULE CHANGE !== A PUBLIC API CHANGE
  47. 47. WHICH MEANS YOU COULD BE HIT BY A MINOR VERSION BUMP
  48. 48. WHICH COULD RESULT IN A FAILING APPLICATION
  49. 49. 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
  50. 50. SO WHY USE IT?
  51. 51. 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
  52. 52. THANKS! DAN JENKINS @dan_jenkins
  53. 53. 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
  • tucq88

    Jul. 12, 2019
  • hoangvv

    Apr. 15, 2019
  • duyehai

    Aug. 20, 2018
  • virajs

    Dec. 3, 2015
  • VicLiu2

    Jun. 29, 2015
  • ASSanonymous

    Jun. 1, 2015
  • VladimirPajic1

    May. 31, 2015
  • JeanPhilippePanis

    May. 31, 2015

Bringing Chaos to order in your node.js app - talk delivered at Node.js Dublin Meetup - talks about the CLS module.

Views

Total views

2,645

On Slideshare

0

From embeds

0

Number of embeds

952

Actions

Downloads

13

Shares

0

Comments

0

Likes

8

×