SlideShare a Scribd company logo
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
FOUNDER OF NIMBLE APE LTD
❤ OPEN SOURCE
3
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 PASTYEAR WORKING ON A PLATFORM CALLED RESPOKE - WEBRTC
8
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 WAYTO SHOW THE POINT IN THE SMALL CONFINES OF A
SLIDE DECK.
I PROMISE I KNOW WHAT I’M DOING…
10
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 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);
});
});
}
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");
});
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");
});
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 ALLTIE TOGETHER
WHAT’S THE ANSWER?
23
OBVIOUSLY…
CLS
NODE-CONTINUATION-LOCAL-STORAGE
USERLAND MODULE
UTILISES ASYNC-LISTENER
24
/othiym23/node-continuation-local-storage
/ continuation-local-storage
/package/async-listener
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
callbacks instead of threads.”
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");
});
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');
});
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 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();
});
}
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);
}
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) {
return function () {
console.log("Starting request!");
var returned = original.apply(this, arguments)
console.log("Done setting up request -- OH YEAH!");
return returned;
};
});
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-promise')(ns);
require('cls-bcrypt')(ns);
42
YOU NEED TO BE WARY!
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));
};
});
};
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 DATA IN THE NAMESPACE
KEEP THINGS TO A MINIMUM
50
SO WHY USE IT?
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
THANKS!
DAN JENKINS
@dan_jenkins
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

More Related Content

What's hot

Open Canary - novahackers
Open Canary - novahackersOpen Canary - novahackers
Open Canary - novahackers
Chris Gates
 
HTTP/3 is next generation HTTP
HTTP/3 is next generation HTTPHTTP/3 is next generation HTTP
HTTP/3 is next generation HTTP
Daniel Stenberg
 
Landing code in curl
Landing code in curlLanding code in curl
Landing code in curl
Daniel Stenberg
 
Getting started with libcurl
Getting started with libcurlGetting started with libcurl
Getting started with libcurl
Daniel Stenberg
 
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
Alessandro Polidori
 
HTTP/3 an early overview
HTTP/3 an early overviewHTTP/3 an early overview
HTTP/3 an early overview
Praveen Kottarathil
 
HTTP/2 and SAP Fiori
HTTP/2 and SAP FioriHTTP/2 and SAP Fiori
HTTP/2 and SAP Fiori
Sascha Wenninger
 
Why async matters
Why async mattersWhy async matters
Why async matters
timbc
 
Presentation at JSConf.be 2019 - Alessandro Polidori
Presentation at JSConf.be 2019 - Alessandro PolidoriPresentation at JSConf.be 2019 - Alessandro Polidori
Presentation at JSConf.be 2019 - Alessandro Polidori
Alessandro Polidori
 
Modern Perl for the Unfrozen Paleolithic Perl Programmer
Modern Perl for the Unfrozen Paleolithic Perl ProgrammerModern Perl for the Unfrozen Paleolithic Perl Programmer
Modern Perl for the Unfrozen Paleolithic Perl Programmer
John Anderson
 
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
Pôle Systematic Paris-Region
 
Package manages and Puppet - PuppetConf 2015
Package manages and Puppet - PuppetConf 2015Package manages and Puppet - PuppetConf 2015
Package manages and Puppet - PuppetConf 2015
ice799
 
Puppet Camp LA 2/19/2015
Puppet Camp LA 2/19/2015Puppet Camp LA 2/19/2015
Puppet Camp LA 2/19/2015
ice799
 
SWIFT: Tango's Infrastructure For Real-Time Video Call Service
SWIFT: Tango's Infrastructure For Real-Time Video Call ServiceSWIFT: Tango's Infrastructure For Real-Time Video Call Service
SWIFT: Tango's Infrastructure For Real-Time Video Call Service
Meng ZHANG
 
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) - Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
Puppet
 
Automate Yo' Self
Automate Yo' SelfAutomate Yo' Self
Automate Yo' Self
John Anderson
 
Debugging PHP with xDebug inside of Eclipse PDT 2.1
Debugging PHP with xDebug inside of Eclipse PDT 2.1Debugging PHP with xDebug inside of Eclipse PDT 2.1
Debugging PHP with xDebug inside of Eclipse PDT 2.1
Bastian Feder
 
DevOOPS: Attacks and Defenses for DevOps Toolchains
DevOOPS: Attacks and Defenses for DevOps ToolchainsDevOOPS: Attacks and Defenses for DevOps Toolchains
DevOOPS: Attacks and Defenses for DevOps Toolchains
Chris Gates
 
HTTP/2 in Examples
HTTP/2 in ExamplesHTTP/2 in Examples
HTTP/2 in Examples
Mihail Stoynov
 
Chef Conf 2015: Package Management & Chef
Chef Conf 2015: Package Management & ChefChef Conf 2015: Package Management & Chef
Chef Conf 2015: Package Management & Chef
ice799
 

What's hot (20)

Open Canary - novahackers
Open Canary - novahackersOpen Canary - novahackers
Open Canary - novahackers
 
HTTP/3 is next generation HTTP
HTTP/3 is next generation HTTPHTTP/3 is next generation HTTP
HTTP/3 is next generation HTTP
 
Landing code in curl
Landing code in curlLanding code in curl
Landing code in curl
 
Getting started with libcurl
Getting started with libcurlGetting started with libcurl
Getting started with libcurl
 
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
Presentation at ClueCon 2019 - Chicago, IL, USA 🇺🇸
 
HTTP/3 an early overview
HTTP/3 an early overviewHTTP/3 an early overview
HTTP/3 an early overview
 
HTTP/2 and SAP Fiori
HTTP/2 and SAP FioriHTTP/2 and SAP Fiori
HTTP/2 and SAP Fiori
 
Why async matters
Why async mattersWhy async matters
Why async matters
 
Presentation at JSConf.be 2019 - Alessandro Polidori
Presentation at JSConf.be 2019 - Alessandro PolidoriPresentation at JSConf.be 2019 - Alessandro Polidori
Presentation at JSConf.be 2019 - Alessandro Polidori
 
Modern Perl for the Unfrozen Paleolithic Perl Programmer
Modern Perl for the Unfrozen Paleolithic Perl ProgrammerModern Perl for the Unfrozen Paleolithic Perl Programmer
Modern Perl for the Unfrozen Paleolithic Perl Programmer
 
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
PyParis 2017 / Writing a C Python extension in 2017, Jean-Baptiste Aviat
 
Package manages and Puppet - PuppetConf 2015
Package manages and Puppet - PuppetConf 2015Package manages and Puppet - PuppetConf 2015
Package manages and Puppet - PuppetConf 2015
 
Puppet Camp LA 2/19/2015
Puppet Camp LA 2/19/2015Puppet Camp LA 2/19/2015
Puppet Camp LA 2/19/2015
 
SWIFT: Tango's Infrastructure For Real-Time Video Call Service
SWIFT: Tango's Infrastructure For Real-Time Video Call ServiceSWIFT: Tango's Infrastructure For Real-Time Video Call Service
SWIFT: Tango's Infrastructure For Real-Time Video Call Service
 
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) - Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
Puppet Camp Atlanta 2014: DEV Toolsets for Ops (Beginner) -
 
Automate Yo' Self
Automate Yo' SelfAutomate Yo' Self
Automate Yo' Self
 
Debugging PHP with xDebug inside of Eclipse PDT 2.1
Debugging PHP with xDebug inside of Eclipse PDT 2.1Debugging PHP with xDebug inside of Eclipse PDT 2.1
Debugging PHP with xDebug inside of Eclipse PDT 2.1
 
DevOOPS: Attacks and Defenses for DevOps Toolchains
DevOOPS: Attacks and Defenses for DevOps ToolchainsDevOOPS: Attacks and Defenses for DevOps Toolchains
DevOOPS: Attacks and Defenses for DevOps Toolchains
 
HTTP/2 in Examples
HTTP/2 in ExamplesHTTP/2 in Examples
HTTP/2 in Examples
 
Chef Conf 2015: Package Management & Chef
Chef Conf 2015: Package Management & ChefChef Conf 2015: Package Management & Chef
Chef Conf 2015: Package Management & Chef
 

Similar to Bringing choas to order in your node.js app

DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
Evaldo Felipe
 
Node.js: CAMTA Presentation
Node.js: CAMTA PresentationNode.js: CAMTA Presentation
Node.js: CAMTA Presentation
Rob Tweed
 
Fun with Ruby and Cocoa
Fun with Ruby and CocoaFun with Ruby and Cocoa
Fun with Ruby and Cocoa
Patrick Huesler
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
David Padbury
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
Aarti Parikh
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.js
Mike Hagedorn
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
Chris Cowan
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
Perl Careers
 
Who pulls the strings?
Who pulls the strings?Who pulls the strings?
Who pulls the strings?
Ronny
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHPphp[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
Adam Englander
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
Ivano Pagano
 
Zend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHPZend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHP
Adam Englander
 
Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)
Daniel Luxemburg
 
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
Sandro Zaccarini
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
Dr Nic Williams
 
Introduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCatsIntroduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCats
Derek Anderson
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
Fatc
FatcFatc
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
Troy Miles
 

Similar to Bringing choas to order in your node.js app (20)

DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
 
Node.js: CAMTA Presentation
Node.js: CAMTA PresentationNode.js: CAMTA Presentation
Node.js: CAMTA Presentation
 
Fun with Ruby and Cocoa
Fun with Ruby and CocoaFun with Ruby and Cocoa
Fun with Ruby and Cocoa
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.js
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Who pulls the strings?
Who pulls the strings?Who pulls the strings?
Who pulls the strings?
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHPphp[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
 
Zend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHPZend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHP
 
Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)
 
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
Pentesting an unfriendly environment: bypassing (un)common defences and mate ...
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
 
Introduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCatsIntroduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCats
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Fatc
FatcFatc
Fatc
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 

More from Dan Jenkins

Yup... WebRTC Still Sucks
Yup... WebRTC Still SucksYup... WebRTC Still Sucks
Yup... WebRTC Still Sucks
Dan Jenkins
 
Professional AV with WebRTC
Professional AV with WebRTCProfessional AV with WebRTC
Professional AV with WebRTC
Dan Jenkins
 
SIMCON 3
SIMCON 3SIMCON 3
SIMCON 3
Dan Jenkins
 
Getting started with WebRTC
Getting started with WebRTCGetting started with WebRTC
Getting started with WebRTC
Dan Jenkins
 
JanusCon - Building Native Mobile Apps with WebRTC
JanusCon - Building Native Mobile Apps with WebRTCJanusCon - Building Native Mobile Apps with WebRTC
JanusCon - Building Native Mobile Apps with WebRTC
Dan Jenkins
 
Getting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackferenceGetting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackference
Dan Jenkins
 
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack TorontoGetting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
Dan Jenkins
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
Dan Jenkins
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
Dan Jenkins
 
WebRTC Reborn SignalConf 2016
WebRTC Reborn SignalConf 2016WebRTC Reborn SignalConf 2016
WebRTC Reborn SignalConf 2016
Dan Jenkins
 
Web technology is getting physical, join the journey
Web technology is getting physical, join the journeyWeb technology is getting physical, join the journey
Web technology is getting physical, join the journey
Dan Jenkins
 
Building the Best Experience for Your Customers and Your Business
Building the Best Experience for Your Customers and Your BusinessBuilding the Best Experience for Your Customers and Your Business
Building the Best Experience for Your Customers and Your Business
Dan Jenkins
 
WebRTC Reborn - Full Stack Toronto
WebRTC Reborn -  Full Stack TorontoWebRTC Reborn -  Full Stack Toronto
WebRTC Reborn - Full Stack Toronto
Dan Jenkins
 
WebRTC Reborn - Cloud Expo / WebRTC Summit
WebRTC Reborn - Cloud Expo / WebRTC SummitWebRTC Reborn - Cloud Expo / WebRTC Summit
WebRTC Reborn - Cloud Expo / WebRTC Summit
Dan Jenkins
 
WebRTC Reborn - Full Stack
WebRTC Reborn  - Full StackWebRTC Reborn  - Full Stack
WebRTC Reborn - Full Stack
Dan Jenkins
 
Developing Yourself for Industry - University of Kent EDA MTD DA
Developing Yourself for Industry - University of Kent EDA MTD DADeveloping Yourself for Industry - University of Kent EDA MTD DA
Developing Yourself for Industry - University of Kent EDA MTD DA
Dan Jenkins
 
Building 21st Century Contact Centre Applications
Building 21st Century Contact Centre ApplicationsBuilding 21st Century Contact Centre Applications
Building 21st Century Contact Centre Applications
Dan Jenkins
 
WebRTC Reborn Hackference
WebRTC Reborn HackferenceWebRTC Reborn Hackference
WebRTC Reborn Hackference
Dan Jenkins
 
WebRTC Reborn Over The Air
WebRTC Reborn Over The AirWebRTC Reborn Over The Air
WebRTC Reborn Over The Air
Dan Jenkins
 
WebRTC Reborn London Node User Group
WebRTC Reborn London Node User GroupWebRTC Reborn London Node User Group
WebRTC Reborn London Node User Group
Dan Jenkins
 

More from Dan Jenkins (20)

Yup... WebRTC Still Sucks
Yup... WebRTC Still SucksYup... WebRTC Still Sucks
Yup... WebRTC Still Sucks
 
Professional AV with WebRTC
Professional AV with WebRTCProfessional AV with WebRTC
Professional AV with WebRTC
 
SIMCON 3
SIMCON 3SIMCON 3
SIMCON 3
 
Getting started with WebRTC
Getting started with WebRTCGetting started with WebRTC
Getting started with WebRTC
 
JanusCon - Building Native Mobile Apps with WebRTC
JanusCon - Building Native Mobile Apps with WebRTCJanusCon - Building Native Mobile Apps with WebRTC
JanusCon - Building Native Mobile Apps with WebRTC
 
Getting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackferenceGetting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackference
 
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack TorontoGetting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
 
WebRTC Reborn SignalConf 2016
WebRTC Reborn SignalConf 2016WebRTC Reborn SignalConf 2016
WebRTC Reborn SignalConf 2016
 
Web technology is getting physical, join the journey
Web technology is getting physical, join the journeyWeb technology is getting physical, join the journey
Web technology is getting physical, join the journey
 
Building the Best Experience for Your Customers and Your Business
Building the Best Experience for Your Customers and Your BusinessBuilding the Best Experience for Your Customers and Your Business
Building the Best Experience for Your Customers and Your Business
 
WebRTC Reborn - Full Stack Toronto
WebRTC Reborn -  Full Stack TorontoWebRTC Reborn -  Full Stack Toronto
WebRTC Reborn - Full Stack Toronto
 
WebRTC Reborn - Cloud Expo / WebRTC Summit
WebRTC Reborn - Cloud Expo / WebRTC SummitWebRTC Reborn - Cloud Expo / WebRTC Summit
WebRTC Reborn - Cloud Expo / WebRTC Summit
 
WebRTC Reborn - Full Stack
WebRTC Reborn  - Full StackWebRTC Reborn  - Full Stack
WebRTC Reborn - Full Stack
 
Developing Yourself for Industry - University of Kent EDA MTD DA
Developing Yourself for Industry - University of Kent EDA MTD DADeveloping Yourself for Industry - University of Kent EDA MTD DA
Developing Yourself for Industry - University of Kent EDA MTD DA
 
Building 21st Century Contact Centre Applications
Building 21st Century Contact Centre ApplicationsBuilding 21st Century Contact Centre Applications
Building 21st Century Contact Centre Applications
 
WebRTC Reborn Hackference
WebRTC Reborn HackferenceWebRTC Reborn Hackference
WebRTC Reborn Hackference
 
WebRTC Reborn Over The Air
WebRTC Reborn Over The AirWebRTC Reborn Over The Air
WebRTC Reborn Over The Air
 
WebRTC Reborn London Node User Group
WebRTC Reborn London Node User GroupWebRTC Reborn London Node User Group
WebRTC Reborn London Node User Group
 

Recently uploaded

2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 

Recently uploaded (20)

2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 

Bringing choas to order in your node.js app

  • 1. BRINGING CHAOS TO ORDER IN YOUR NODE.JS APP DAN JENKINS NIMBLE APE https://nimblea.pe
  • 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
  • 7.
  • 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
  • 9. FUNNY STORY… 9 H E L L O my name is Dan G O O G L E I / O
  • 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
  • 11. NODE.JS APPS CAN GET IN A REAL MESS…
  • 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"); });
  • 15. EVERYONE HAS AT SOME POINT…
  • 16. DON’T TRY AND DENY IT…
  • 17. WHAT PROBLEM ARE WE TRYING TO SOLVE?
  • 18. PASSING DATA AROUND TO OTHER FUNCTIONS FOR USE LATER
  • 21. 21 ASSIGN A REQUEST ID HERE AND HAVE IT SENT ON TO ALL OTHER SERVICES WHICH MEANS ALLYOUR LOGS FROM ALLYOUR SERVICES ALLTIE TOGETHER
  • 25. IT HAS NOTHING TO DO WITH LOCAL-STORAGE IN THE BROWSER
  • 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'); });
  • 29. IT’S MORE IMPRESSIVE THAN IT LOOKS IN THIS SIMPLE EXAMPLE I PROMISE
  • 30. THAT’S AWESOME! WHAT DO I NEED TO DO?
  • 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?
  • 36. ANYTHING THAT TOUCHES NATIVE CODE; YOU’LL NEED TO SHIM
  • 37. SHIM ALL THE THINGS
  • 39. 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; }; });
  • 40. OR USE AN EXISTING ONE
  • 42. 42
  • 43. YOU NEED TO BE WARY!
  • 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)); }; }); };
  • 45. YOU HAVE TO KNOW WHAT TO SHIM!
  • 46. AND BEWARE THE INTERNALS OF THE MODULE CHANGING
  • 47. AN INTERNAL MODULE CHANGE !== A PUBLIC API CHANGE
  • 48. WHICH MEANS YOU COULD BE HIT BY A MINOR VERSION BUMP
  • 49. WHICH COULD RESULT IN A FAILING APPLICATION
  • 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
  • 51. SO WHY USE IT?
  • 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