Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd530c2

Browse files
kjarmickidougwilson
authored andcommitted
Prevent loss of async hooks context
closes #36
1 parent 6cfbc00 commit cd530c2

File tree

3 files changed

+149
-14
lines changed

3 files changed

+149
-14
lines changed

HISTORY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
unreleased
2+
==========
3+
4+
* Prevent loss of async hooks context
5+
16
2.3.0 / 2015-05-26
27
==================
38

index.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module.exports.isFinished = isFinished
2020
* @private
2121
*/
2222

23+
var asyncHooks = tryRequireAsyncHooks()
2324
var first = require('ee-first')
2425

2526
/**
@@ -49,7 +50,7 @@ function onFinished (msg, listener) {
4950
}
5051

5152
// attach the listener to the message
52-
attachListener(msg, listener)
53+
attachListener(msg, wrap(listener))
5354

5455
return msg
5556
}
@@ -195,3 +196,33 @@ function patchAssignSocket (res, callback) {
195196
callback(socket)
196197
}
197198
}
199+
200+
/**
201+
* Try to require async_hooks
202+
* @private
203+
*/
204+
205+
function tryRequireAsyncHooks () {
206+
try {
207+
return require('async_hooks')
208+
} catch (e) {
209+
/* istanbul ignore next */
210+
return {}
211+
}
212+
}
213+
214+
/**
215+
* Wrap function with async resource
216+
* @private
217+
*/
218+
219+
function wrap (fn) {
220+
if (!asyncHooks.AsyncResource) {
221+
/* istanbul ignore next */
222+
return fn
223+
}
224+
225+
// AsyncResource.bind static method backported
226+
var res = new asyncHooks.AsyncResource(fn.name || 'bound-anonymous-fn')
227+
return res.runInAsyncScope.bind(res, fn, null)
228+
}

test/test.js

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11

22
var assert = require('assert')
3+
var asyncHooks = tryRequire('async_hooks')
34
var http = require('http')
45
var net = require('net')
56
var onFinished = require('..')
67

8+
var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function'
9+
? describe
10+
: describe.skip
11+
712
describe('onFinished(res, listener)', function () {
813
it('should invoke listener given an unknown object', function (done) {
914
onFinished({}, done)
@@ -32,15 +37,57 @@ describe('onFinished(res, listener)', function () {
3237
sendGet(server)
3338
})
3439

35-
it('should fire when called after finish', function (done) {
36-
var server = http.createServer(function (req, res) {
37-
onFinished(res, function () {
38-
onFinished(res, done)
40+
describe('when called after finish', function () {
41+
it('should fire when called after finish', function (done) {
42+
var server = http.createServer(function (req, res) {
43+
onFinished(res, function () {
44+
onFinished(res, done)
45+
})
46+
setTimeout(res.end.bind(res), 0)
3947
})
40-
setTimeout(res.end.bind(res), 0)
48+
49+
sendGet(server)
4150
})
4251

43-
sendGet(server)
52+
describeAsyncHooks('when async local storage', function () {
53+
it('should presist store in callback', function (done) {
54+
var asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
55+
var store = { foo: 'bar' }
56+
57+
var server = http.createServer(function (req, res) {
58+
onFinished(res, function () {
59+
asyncLocalStorage.run(store, function () {
60+
onFinished(res, function () {
61+
assert.strictEqual(asyncLocalStorage.getStore().foo, 'bar')
62+
done()
63+
})
64+
})
65+
})
66+
setTimeout(res.end.bind(res), 0)
67+
})
68+
69+
sendGet(server)
70+
})
71+
})
72+
})
73+
74+
describeAsyncHooks('when async local storage', function () {
75+
it('should presist store in callback', function (done) {
76+
var asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
77+
var store = { foo: 'bar' }
78+
79+
var server = http.createServer(function (req, res) {
80+
asyncLocalStorage.run(store, function () {
81+
onFinished(res, function () {
82+
assert.strictEqual(asyncLocalStorage.getStore().foo, 'bar')
83+
done()
84+
})
85+
})
86+
setTimeout(res.end.bind(res), 0)
87+
})
88+
89+
sendGet(server)
90+
})
4491
})
4592
})
4693

@@ -385,16 +432,60 @@ describe('onFinished(req, listener)', function () {
385432
sendGet(server)
386433
})
387434

388-
it('should fire when called after finish', function (done) {
389-
var server = http.createServer(function (req, res) {
390-
onFinished(req, function () {
391-
onFinished(req, done)
435+
describe('when called after finish', function () {
436+
it('should fire when called after finish', function (done) {
437+
var server = http.createServer(function (req, res) {
438+
onFinished(req, function () {
439+
onFinished(req, done)
440+
})
441+
req.resume()
442+
setTimeout(res.end.bind(res), 0)
392443
})
393-
req.resume()
394-
setTimeout(res.end.bind(res), 0)
444+
445+
sendGet(server)
395446
})
396447

397-
sendGet(server)
448+
describeAsyncHooks('when async local storage', function () {
449+
it('should presist store in callback', function (done) {
450+
var asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
451+
var store = { foo: 'bar' }
452+
453+
var server = http.createServer(function (req, res) {
454+
onFinished(req, function () {
455+
asyncLocalStorage.run(store, function () {
456+
onFinished(req, function () {
457+
assert.strictEqual(asyncLocalStorage.getStore().foo, 'bar')
458+
done()
459+
})
460+
})
461+
})
462+
req.resume()
463+
setTimeout(res.end.bind(res), 0)
464+
})
465+
466+
sendGet(server)
467+
})
468+
})
469+
})
470+
471+
describeAsyncHooks('when async local storage', function () {
472+
it('should presist store in callback', function (done) {
473+
var asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
474+
var store = { foo: 'bar' }
475+
476+
var server = http.createServer(function (req, res) {
477+
asyncLocalStorage.run(store, function () {
478+
onFinished(req, function () {
479+
assert.strictEqual(asyncLocalStorage.getStore().foo, 'bar')
480+
done()
481+
})
482+
})
483+
req.resume()
484+
setTimeout(res.end.bind(res), 0)
485+
})
486+
487+
sendGet(server)
488+
})
398489
})
399490
})
400491

@@ -1068,6 +1159,14 @@ function sendGet (server) {
10681159
})
10691160
}
10701161

1162+
function tryRequire (name) {
1163+
try {
1164+
return require(name)
1165+
} catch (e) {
1166+
return {}
1167+
}
1168+
}
1169+
10711170
function writeRequest (socket, chunked) {
10721171
socket.write('GET / HTTP/1.1\r\n')
10731172
socket.write('Host: localhost\r\n')

0 commit comments

Comments
 (0)