Skip to content
This repository was archived by the owner on Apr 25, 2019. It is now read-only.

Commit 7ad69d1

Browse files
author
Russell Cohen
committed
Adds reqInfo object to pool.request callback
This change is a little specific, so no pressure to merge. It adds an additional callback argument to pool.request, namely, requestInfo. It is a dictionary containing information about the node that responded to the request, nodes that failed to respond to the request, and the number of total retries. It does this by creating a closure when preparing to handle the response containing the node that the response is coming from.
1 parent cc79dfa commit 7ad69d1

4 files changed

Lines changed: 52 additions & 6 deletions

File tree

lib/pool.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ module.exports = function (inherits, EventEmitter, Endpoint, RequestSet) {
124124
options.stream = (options.stream === undefined) ? callback.length === 2 : options.stream
125125

126126
var started = Date.now()
127-
RequestSet.request(this, options, function (err, res, body) {
127+
RequestSet.request(this, options, function (err, res, body, reqInfo) {
128128
options.success = !err
129129
options.reused = res && res.socket && (res.socket._requestCount || 1) > 1
130130
self.emit('timing', Date.now() - started, options)
131-
callback(err, res, body)
131+
callback(err, res, body, reqInfo)
132132
})
133133
}
134134

lib/request_set.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,21 @@ function exponentialBackoff(attempt, delay) {
4141
return Math.random() * Math.pow(2, attempt) * delay
4242
}
4343

44+
function handleResponseFromNode(node) {
45+
return function(err, response, body) {
46+
return handleResponse.bind(this)(err, response, body, node);
47+
}
48+
}
49+
4450
// this = RequestSet
45-
function handleResponse(err, response, body) {
51+
function handleResponse(err, response, body, respondingNode) {
4652
this.attemptsLeft--
53+
if (!this.reqInfo) { this.reqInfo = {} };
4754
if (err) {
55+
if (!this.reqInfo.failedNodes) {
56+
this.reqInfo.failedNodes = [];
57+
}
58+
this.reqInfo.failedNodes.push(respondingNode.name);
4859
var delay = (err.delay === true)
4960
? exponentialBackoff(this.attempts - this.attemptsLeft, this.delay)
5061
: err.delay
@@ -63,7 +74,12 @@ function handleResponse(err, response, body) {
6374
}
6475
}
6576
if (this.callback) {
66-
this.callback(err, response, body)
77+
this.reqInfo.numRetries = this.attempts - this.attemptsLeft;
78+
if (respondingNode) {
79+
this.reqInfo.respondingNode = respondingNode.name;
80+
}
81+
82+
this.callback(err, response, body, this.reqInfo)
6783
this.callback = null
6884
}
6985
}
@@ -86,7 +102,7 @@ RequestSet.request = function (pool, options, callback) {
86102

87103
RequestSet.prototype.doRequest = function () {
88104
var node = this.pool.get_node()
89-
node.request(this.options, handleResponse.bind(this))
105+
node.request(this.options, handleResponseFromNode(node).bind(this))
90106
}
91107

92108
module.exports = RequestSet

readme.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ pool.request(
175175
, stream: false // stream instead of buffer response body
176176
}
177177
,
178-
function (error, response, body) {}
178+
function (error, response, body, requestInfo) {}
179179
)
180180
```
181181

@@ -193,6 +193,16 @@ pool.request(
193193
A callback with 2 arguments will stream the response and not buffer the
194194
response body.
195195

196+
The fourth callback argument, `requestInfo` contains information about how the request was handled by
197+
the pool, namely:
198+
199+
```javascript
200+
{ numRetries: 3 // number of times the request was made
201+
, failedNodes: ['www.foo.com:99', 'www.foo2.com:99'] // nodes that failed to handle the request
202+
, respondingNode: 'www.foo3.com:99' // The node that handled the request sucesfully
203+
}
204+
```
205+
196206
```javascript
197207
pool.request('/foo', function (error, response) {
198208
response.pipe(somewhere)

test/requestset_test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,26 @@ describe("RequestSet", function () {
108108
})
109109
})
110110

111+
it("passes back a requestInfo containing information about the request", function(done) {
112+
var p = {
113+
i: 0,
114+
options: { maxRetries: 5 },
115+
get_node: function () { return this.nodes[this.i++]},
116+
onRetry: function () {},
117+
length: 3,
118+
nodes: [{ name: "fail_node", request: hangup_request }, {name: "fail_node2", request: failing_request}, { name: "succeed_node", request: succeeding_request }]
119+
}
120+
RequestSet.request(p, {}, function (err, res, body, requestInfo) {
121+
assert.equal(err, null)
122+
assert.equal(body, "foo")
123+
assert(requestInfo, "requestInfo should be non-null");
124+
assert.deepEqual(requestInfo.failedNodes, ['fail_node', 'fail_node2']);
125+
assert.deepEqual(requestInfo.respondingNode, 'succeed_node');
126+
assert.equal(requestInfo.numRetries, 3);
127+
done()
128+
})
129+
});
130+
111131
it("retries hangups identically to other requests then fails", function (done) {
112132
var p = {
113133
i: 0,

0 commit comments

Comments
 (0)