SlideShare a Scribd company logo
1 of 24
Domains!
BY @DOMENIC
Domenic Denicola
• http://domenic.me
• https://github.com/domenic
• https://npmjs.org/~domenic
• http://slideshare.net/domenicdenicola
Things I’m doing:
• @esdiscuss onTwitter
• The Promises/A+ spec
• Client-Side Packages talk
@DOMENIC
Let’s talk about errors in
@DOMENIC
• Errors passed to a callback: beAsync(function (err, result) { … })
• Errors emitted from an event emitter: emitter.emit('error', err)
• Errors thrown “intentionally”: throw err
• Errors thrown “accidentally”: JSON.parse(badUserInput)
@DOMENIC
IF AN ERROR IS THROWN,
BUT NOBODY CATCHES IT,
DOES IT MAKE A SOUND?
Answer: yes!!
@DOMENIC
• Errors passed to a callback: beAsync(function (err, result) { … })
• Errors emitted from an event emitter: emitter.emit('error', err)
• Errors thrown “intentionally”: throw err
• Errors thrown “accidentally”: JSON.parse(badUserInput)
SERVER GO CRASH
DEMOTIME
@DOMENIC
https://github.com/domenic/domains-romance/blob/master/server.js
Before domains: process.on('uncaughtException', …)
• Instead of crashing, you could listen for “about to crash,” and do
something about it.
• But: how do you keep track of what caused the crash?
• Concretely: how can you return a 500 error to the right request?
• Domains are supposed to help with this… somehow.
@DOMENIC
Build your own domains: uncaught throws
• Before initiating some asynchronous work:
• process.pseudoDomain = new EventEmitter();
• After initiating the async work:
• process.pseudoDomain = null;
• Inside your 'uncaughtException' handler:
• if (process.pseudoDomain) process.pseudoDomain.emit('error', err);
• Now, in the pseudo-domain’s 'error' handler, you know the cause!
@DOMENIC
Build your own domains: unheard 'error's
• When creating an event emitter:
• ee.pseudoDomain = new EventEmitter();
• ee.on('error', function (err) {
if (EventEmitter.listenerCount(this, 'error') === 1) {
this.pseudoDomain.emit('error', err);
}
});
• Now, in the pseudo-domain’s 'error' handler, you know the cause!
@DOMENIC
Build your own domains: callback err params
• function bindToDomain(domain, cb) {
return function (err, result) {
if (err) return domain.emit('error', err);
cb(null, result);
};
}
• Every time you use a callback:
• var pseudoDomain = new EventEmitter();
• doAsyncThing(bindToDomain(pseudoDomain, function (result) { … });
• Now, in the pseudo-domain’s 'error' handler, you know the cause!
@DOMENIC
The key feature: automatic aggregation
• This is pretty useless if you have to create a domain for every async
operation.You might as well keep track of things yourself.
• But what if we assigned a single domain to a whole bunch of async
operations?
• Say, every async operation involved in a single HTTP
request/response cycle?
• What if we had hooks into every asynchronous function and every
event emitter in Node.js, to automatically associate with an
“active” domain?
@DOMENIC
DEMOTIME
@DOMENIC
https://github.com/domenic/domains-romance/blob/master/serverWithDomains.js
But … how!?
To understand how domains hook in to all that, we’re going
to need to take a journey into the heart of Node.js.
@DOMENIC
MakeCallback
node.cc line 1001:
Handle<Value> MakeCallback(const Handle<Object> object,
const Handle<Function> callback,
int argc, Handle<value> argv[]) {
⋮
TryCatch try_catch;
Local<Value> ret = callback->Call(object, argc, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
⋮
@DOMENIC
Domain basics
• var d = require('domain').create();
• There’s a globally active current domain:
• process.domain === require('domain').active
• (There’s actually a stack, so you can recursively enter domains, but whatevs.)
• d.enter() makes d the current domain.
• d.exit() makes d inactive.
• d.run(func) is shorthand for d.enter(); func(); d.exit().
@DOMENIC
Effects of having an active domain
• MakeCallback is most directly influenced
• process.domain.enter() and process.domain.exit() wrap the previous code
• setImmediate, setTimeout, setInterval, process.nextTick
• record the active domain and attach it to the callback (1, 2, 3, 4)
• when the callback is triggered, wrap it with enter() and exit() (1, 2/3, 4)
• new EventEmitter()
• records the active domain and attach it to the emitter
• when any events are emitted, wraps with enter() and exit()
• when an 'error' event is emitted and not handled, gives it to the domain
@DOMENIC
(mmm, yummy global state…)
Uncaught exceptions
• Remember FatalException(try_catch)?
• That calls from C++ to process._fatalException (node.js line 222)
• Much like in our pseudo-domains, it hands them off to the active
domain’s 'error' handler.
• Thus all the enter()/exit() wrapping was just establishing context for this
moment: deciding which domain gets the errors.
• If there is an active domain, this behavior replaces
'uncaughtException'.
@DOMENIC
That’s cool. Now what?
We know how domains work.
But do we truly know how to use them?
@DOMENIC
Stability 2: Unstable
“TheAPI is in the process of settling, but has not yet had sufficient
real-world testing to be considered stable. Backwards-compatibility
will be maintained if reasonable.” (source)
• Don’t use d.dispose().
@DOMENIC
APIs to know
• domain.create(), obviously
• d.run(), to enter/exit the domain
• d.add(), for adding event emitters created before the domain
existed into the domain.
• d.bind(), for manually wiring up a callback to a domain.
• d.intercept(), that callback helper from before.
@DOMENIC
EventEmitter pitfalls
• Event emitters are bound to a domain on creation. But sometimes
event emitters stick around for a long time.
• Any callbacks given to the event emitter “escape” the active
domain, which is replaced by whatever the active domain was
when the event emitter was created.
• Generally, anything involving a persistent connection or
connection pool will be in trouble, and not able to associate errors
with the currently-active domain.
• https://github.com/domenic/domains-tragedy
@DOMENIC
Error recovery
• Domains don’t give you try/catch back.
• By the time you see an error on the domain, it escaped any close-
to-the-source error handling; nobody handled it explicitly.
• You’re probably in an inconsistent state, halfway through a
transaction or with file handles open or who knows what.
• The recommendation is to gracefully return a 500, then shut down
your worker and restart while others in the cluster take over.
@DOMENIC
Versus promises
• Domains have grown … organically.
• Promises attempt to solve error handling from first principles, by
giving you back return and throw semantics.
• In practice, this means wrapping every callback in try/catch, much
like MakeCallback, but less pervasively and more intelligently.
• But, they won’t save you completely in Node.js:
• 'error' events are still fatal
• If you step outside of promise-land, e.g. setTimeout, uncaught exceptions
are again dangerous.
@DOMENIC
IN CONCLUSION
• Domains work pretty well to tame
async errors in Node.js.
• They do so by hooking into Node.js at
the deepest level.
• They don’t work perfectly, and they
don’t absolve you of cleanup.
• But you should be able to get some
solid wins with minimal extra code.
@DOMENIC

More Related Content

What's hot

Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript PromisesTomasz Bak
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node jsThomas Roch
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous Shmuel Fomberg
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Libraryasync_io
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perldeepfountainconsulting
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
Avoiding callback hell with promises
Avoiding callback hell with promisesAvoiding callback hell with promises
Avoiding callback hell with promisesTorontoNodeJS
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)xSawyer
 
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.jsMike Hagedorn
 
Any event intro
Any event introAny event intro
Any event introqiang
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3Luciano Mammino
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Nilesh Jayanandana
 

What's hot (20)

Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
A Gentle Introduction to Event Loops
A Gentle Introduction to Event LoopsA Gentle Introduction to Event Loops
A Gentle Introduction to Event Loops
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node js
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
Avoiding callback hell with promises
Avoiding callback hell with promisesAvoiding callback hell with promises
Avoiding callback hell with promises
 
C to perl binding
C to perl bindingC to perl binding
C to perl binding
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
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
 
Any event intro
Any event introAny event intro
Any event intro
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6
 

Similar to Domains Explained

Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great JusticeDomenic Denicola
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js PlatformDomenic Denicola
 
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyFast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyKyle Drake
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkRyan Weaver
 
LCA2014 - Introduction to Go
LCA2014 - Introduction to GoLCA2014 - Introduction to Go
LCA2014 - Introduction to Godreamwidth
 
Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 FibersKevin Ball
 
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010Ilya Grigorik
 
Case Study of the Unexplained
Case Study of the UnexplainedCase Study of the Unexplained
Case Study of the Unexplainedshannomc
 
An Introduction to Go
An Introduction to GoAn Introduction to Go
An Introduction to GoCloudflare
 
Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopLuciano Mammino
 
From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017Agustin Ramos
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0GrUSP
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonLuciano Mammino
 
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 talkAarti Parikh
 
Crm saturday madrid 2017 jordi montaña - test automation
Crm saturday madrid 2017   jordi montaña - test automationCrm saturday madrid 2017   jordi montaña - test automation
Crm saturday madrid 2017 jordi montaña - test automationDemian Raschkovan
 
Crm Saturday Madrid - Test Automation for Dynamics 365
Crm Saturday Madrid  - Test Automation for Dynamics 365Crm Saturday Madrid  - Test Automation for Dynamics 365
Crm Saturday Madrid - Test Automation for Dynamics 365Jordi Montaña
 

Similar to Domains Explained (20)

Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyFast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
 
Klee and angr
Klee and angrKlee and angr
Klee and angr
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
LCA2014 - Introduction to Go
LCA2014 - Introduction to GoLCA2014 - Introduction to Go
LCA2014 - Introduction to Go
 
Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 Fibers
 
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 
Case Study of the Unexplained
Case Study of the UnexplainedCase Study of the Unexplained
Case Study of the Unexplained
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
 
An Introduction to Go
An Introduction to GoAn Introduction to Go
An Introduction to Go
 
Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - Workshop
 
From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathon
 
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
 
Crm saturday madrid 2017 jordi montaña - test automation
Crm saturday madrid 2017   jordi montaña - test automationCrm saturday madrid 2017   jordi montaña - test automation
Crm saturday madrid 2017 jordi montaña - test automation
 
Crm Saturday Madrid - Test Automation for Dynamics 365
Crm Saturday Madrid  - Test Automation for Dynamics 365Crm Saturday Madrid  - Test Automation for Dynamics 365
Crm Saturday Madrid - Test Automation for Dynamics 365
 

More from Domenic Denicola

The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)Domenic Denicola
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesDomenic Denicola
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIsDomenic Denicola
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptDomenic Denicola
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 

More from Domenic Denicola (14)

The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
The jsdom
The jsdomThe jsdom
The jsdom
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Streams for the Web
Streams for the WebStreams for the Web
Streams for the Web
 
After Return of the Jedi
After Return of the JediAfter Return of the Jedi
After Return of the Jedi
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards Bodies
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
 
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScript
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 

Recently uploaded

Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

Domains Explained

  • 2. Domenic Denicola • http://domenic.me • https://github.com/domenic • https://npmjs.org/~domenic • http://slideshare.net/domenicdenicola Things I’m doing: • @esdiscuss onTwitter • The Promises/A+ spec • Client-Side Packages talk @DOMENIC
  • 3. Let’s talk about errors in @DOMENIC • Errors passed to a callback: beAsync(function (err, result) { … }) • Errors emitted from an event emitter: emitter.emit('error', err) • Errors thrown “intentionally”: throw err • Errors thrown “accidentally”: JSON.parse(badUserInput)
  • 4. @DOMENIC IF AN ERROR IS THROWN, BUT NOBODY CATCHES IT, DOES IT MAKE A SOUND?
  • 5. Answer: yes!! @DOMENIC • Errors passed to a callback: beAsync(function (err, result) { … }) • Errors emitted from an event emitter: emitter.emit('error', err) • Errors thrown “intentionally”: throw err • Errors thrown “accidentally”: JSON.parse(badUserInput) SERVER GO CRASH
  • 7. Before domains: process.on('uncaughtException', …) • Instead of crashing, you could listen for “about to crash,” and do something about it. • But: how do you keep track of what caused the crash? • Concretely: how can you return a 500 error to the right request? • Domains are supposed to help with this… somehow. @DOMENIC
  • 8. Build your own domains: uncaught throws • Before initiating some asynchronous work: • process.pseudoDomain = new EventEmitter(); • After initiating the async work: • process.pseudoDomain = null; • Inside your 'uncaughtException' handler: • if (process.pseudoDomain) process.pseudoDomain.emit('error', err); • Now, in the pseudo-domain’s 'error' handler, you know the cause! @DOMENIC
  • 9. Build your own domains: unheard 'error's • When creating an event emitter: • ee.pseudoDomain = new EventEmitter(); • ee.on('error', function (err) { if (EventEmitter.listenerCount(this, 'error') === 1) { this.pseudoDomain.emit('error', err); } }); • Now, in the pseudo-domain’s 'error' handler, you know the cause! @DOMENIC
  • 10. Build your own domains: callback err params • function bindToDomain(domain, cb) { return function (err, result) { if (err) return domain.emit('error', err); cb(null, result); }; } • Every time you use a callback: • var pseudoDomain = new EventEmitter(); • doAsyncThing(bindToDomain(pseudoDomain, function (result) { … }); • Now, in the pseudo-domain’s 'error' handler, you know the cause! @DOMENIC
  • 11. The key feature: automatic aggregation • This is pretty useless if you have to create a domain for every async operation.You might as well keep track of things yourself. • But what if we assigned a single domain to a whole bunch of async operations? • Say, every async operation involved in a single HTTP request/response cycle? • What if we had hooks into every asynchronous function and every event emitter in Node.js, to automatically associate with an “active” domain? @DOMENIC
  • 13. But … how!? To understand how domains hook in to all that, we’re going to need to take a journey into the heart of Node.js. @DOMENIC
  • 14. MakeCallback node.cc line 1001: Handle<Value> MakeCallback(const Handle<Object> object, const Handle<Function> callback, int argc, Handle<value> argv[]) { ⋮ TryCatch try_catch; Local<Value> ret = callback->Call(object, argc, argv); if (try_catch.HasCaught()) { FatalException(try_catch); ⋮ @DOMENIC
  • 15. Domain basics • var d = require('domain').create(); • There’s a globally active current domain: • process.domain === require('domain').active • (There’s actually a stack, so you can recursively enter domains, but whatevs.) • d.enter() makes d the current domain. • d.exit() makes d inactive. • d.run(func) is shorthand for d.enter(); func(); d.exit(). @DOMENIC
  • 16. Effects of having an active domain • MakeCallback is most directly influenced • process.domain.enter() and process.domain.exit() wrap the previous code • setImmediate, setTimeout, setInterval, process.nextTick • record the active domain and attach it to the callback (1, 2, 3, 4) • when the callback is triggered, wrap it with enter() and exit() (1, 2/3, 4) • new EventEmitter() • records the active domain and attach it to the emitter • when any events are emitted, wraps with enter() and exit() • when an 'error' event is emitted and not handled, gives it to the domain @DOMENIC (mmm, yummy global state…)
  • 17. Uncaught exceptions • Remember FatalException(try_catch)? • That calls from C++ to process._fatalException (node.js line 222) • Much like in our pseudo-domains, it hands them off to the active domain’s 'error' handler. • Thus all the enter()/exit() wrapping was just establishing context for this moment: deciding which domain gets the errors. • If there is an active domain, this behavior replaces 'uncaughtException'. @DOMENIC
  • 18. That’s cool. Now what? We know how domains work. But do we truly know how to use them? @DOMENIC
  • 19. Stability 2: Unstable “TheAPI is in the process of settling, but has not yet had sufficient real-world testing to be considered stable. Backwards-compatibility will be maintained if reasonable.” (source) • Don’t use d.dispose(). @DOMENIC
  • 20. APIs to know • domain.create(), obviously • d.run(), to enter/exit the domain • d.add(), for adding event emitters created before the domain existed into the domain. • d.bind(), for manually wiring up a callback to a domain. • d.intercept(), that callback helper from before. @DOMENIC
  • 21. EventEmitter pitfalls • Event emitters are bound to a domain on creation. But sometimes event emitters stick around for a long time. • Any callbacks given to the event emitter “escape” the active domain, which is replaced by whatever the active domain was when the event emitter was created. • Generally, anything involving a persistent connection or connection pool will be in trouble, and not able to associate errors with the currently-active domain. • https://github.com/domenic/domains-tragedy @DOMENIC
  • 22. Error recovery • Domains don’t give you try/catch back. • By the time you see an error on the domain, it escaped any close- to-the-source error handling; nobody handled it explicitly. • You’re probably in an inconsistent state, halfway through a transaction or with file handles open or who knows what. • The recommendation is to gracefully return a 500, then shut down your worker and restart while others in the cluster take over. @DOMENIC
  • 23. Versus promises • Domains have grown … organically. • Promises attempt to solve error handling from first principles, by giving you back return and throw semantics. • In practice, this means wrapping every callback in try/catch, much like MakeCallback, but less pervasively and more intelligently. • But, they won’t save you completely in Node.js: • 'error' events are still fatal • If you step outside of promise-land, e.g. setTimeout, uncaught exceptions are again dangerous. @DOMENIC
  • 24. IN CONCLUSION • Domains work pretty well to tame async errors in Node.js. • They do so by hooking into Node.js at the deepest level. • They don’t work perfectly, and they don’t absolve you of cleanup. • But you should be able to get some solid wins with minimal extra code. @DOMENIC

Editor's Notes

  1. Opening story: GothamJS, diving into AngularJS code.
  2. I work here at Lab49!
  3. The first of these, you handle yourself.The second, by design, re-throws the error if there are no listeners for it.The third, since we’re almost always inside a callback, can’t bubble up the call stack; callbacks reset the call stack, so they hit the top of that call stack pretty quickly.—If we were in a browser, those would hit window.onerror.
  4. (On switch back) How can we fix this??
  5. Let’s build our own “domains” to track error sources!
  6. I dug into the source code, and figured out how domains work. This is basically it.
  7. I dug into the source code, and figured out how domains work. This is basically it.
  8. Since we’ve got this working for everything else, might as well try to make callbacks a bit easier to use.
  9. All callbacks you give to Node.js’s code pass through here.Either directly, from C++ code which directly calls MakeCallback to execute your callbackOr indirectly, via a convoluted chain inside src/node.js that ends up in process._makeCallback.
  10. To understand how this gives us the power we need, let’s take a step back and see how the domain object themselves work.
  11. The moment you start using domains all this gets switched out from under you. process._setupDomainUse()BUT: wrapping in enter()/exit() is just the setup. enter() and exit() do literally nothing besides setting the active domain. The magic takes place in our next chapter: