tchannel 3.6.17 → 3.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/channel.js +10 -9
- package/lazy_relay.js +23 -2
- package/lib/object_pool.js +56 -16
- package/package.json +1 -1
- package/peer.js +79 -6
- package/relay_handler.js +1 -0
- package/stat-tags.js +24 -1
- package/test/lib/alloc-cluster.js +23 -1
- package/test/object_pool.js +10 -6
- package/test/relay_lazy.js +2 -1
package/channel.js
CHANGED
|
@@ -230,14 +230,6 @@ function TChannel(options) {
|
|
|
230
230
|
this.statsd = this.options.statsd;
|
|
231
231
|
this.batchStats = null;
|
|
232
232
|
|
|
233
|
-
if (this.statsd) {
|
|
234
|
-
ObjectPool.bootstrap({
|
|
235
|
-
statsd: this.statsd,
|
|
236
|
-
reportInterval: 1000,
|
|
237
|
-
timers: this.timers
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
233
|
this.requestDefaults = this.options.requestDefaults ?
|
|
242
234
|
new RequestDefaults(this.options.requestDefaults) : null;
|
|
243
235
|
|
|
@@ -262,6 +254,15 @@ function TChannel(options) {
|
|
|
262
254
|
this.batchStats = this.topChannel.batchStats;
|
|
263
255
|
}
|
|
264
256
|
|
|
257
|
+
if (this.batchStats) {
|
|
258
|
+
ObjectPool.bootstrap({
|
|
259
|
+
channel: this,
|
|
260
|
+
reportInterval: 5000,
|
|
261
|
+
timers: this.timers,
|
|
262
|
+
debug: this.options.objectPoolDebug ? true : false
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
265
266
|
this.maximumRelayTTL = MAXIMUM_TTL_ALLOWED;
|
|
266
267
|
|
|
267
268
|
function doSanitySweep() {
|
|
@@ -918,7 +919,7 @@ TChannel.prototype.close = function close(callback) {
|
|
|
918
919
|
|
|
919
920
|
var counter = 1;
|
|
920
921
|
|
|
921
|
-
if (self.
|
|
922
|
+
if (self.batchStats) {
|
|
922
923
|
ObjectPool.unref();
|
|
923
924
|
}
|
|
924
925
|
|
package/lazy_relay.js
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
|
+
var process = require('process');
|
|
23
24
|
var errors = require('./errors');
|
|
24
25
|
var v2 = require('./v2');
|
|
25
26
|
var stat = require('./stat-tags.js');
|
|
@@ -61,6 +62,7 @@ function LazyRelayInReq(conn, reqFrame) {
|
|
|
61
62
|
this.tracing = null;
|
|
62
63
|
this.reqContFrames = [];
|
|
63
64
|
this.hasRead = null;
|
|
65
|
+
this.waitForIdentSlot = null;
|
|
64
66
|
|
|
65
67
|
this.boundExtendLogInfo = extendLogInfo;
|
|
66
68
|
this.boundOnIdentified = onIdentified;
|
|
@@ -72,6 +74,10 @@ function LazyRelayInReq(conn, reqFrame) {
|
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
function onIdentified(err) {
|
|
77
|
+
// The ident descriptor will be cleared out of the peer when the ident
|
|
78
|
+
// comes back, so this slot id will be invalid once ident happens.
|
|
79
|
+
self.waitForIdentSlot = -1;
|
|
80
|
+
|
|
75
81
|
if (err) {
|
|
76
82
|
self.onError(err);
|
|
77
83
|
} else {
|
|
@@ -102,6 +108,7 @@ LazyRelayInReq.prototype.reset = function reset(conn, reqFrame) {
|
|
|
102
108
|
this.reqContFrames.length = 0;
|
|
103
109
|
this.hasRead = false;
|
|
104
110
|
this.circuit = reqFrame.circuit;
|
|
111
|
+
this.waitForIdentSlot = null;
|
|
105
112
|
};
|
|
106
113
|
|
|
107
114
|
LazyRelayInReq.prototype.clear = function clear() {
|
|
@@ -109,6 +116,10 @@ LazyRelayInReq.prototype.clear = function clear() {
|
|
|
109
116
|
this.outreq.free();
|
|
110
117
|
}
|
|
111
118
|
|
|
119
|
+
if (this.peer && this.waitForIdentSlot !== null) {
|
|
120
|
+
this.peer.stopWaitingForIdentified(this.waitForIdentSlot);
|
|
121
|
+
}
|
|
122
|
+
|
|
112
123
|
this.channel = null;
|
|
113
124
|
this.conn = null;
|
|
114
125
|
this.start = null;
|
|
@@ -130,6 +141,7 @@ LazyRelayInReq.prototype.clear = function clear() {
|
|
|
130
141
|
this.reqContFrames.length = 0;
|
|
131
142
|
this.hasRead = null;
|
|
132
143
|
this.circuit = null;
|
|
144
|
+
this.waitForIdentSlot = null;
|
|
133
145
|
};
|
|
134
146
|
|
|
135
147
|
ObjectPool.setup({Type: LazyRelayInReq, maxSize: 200});
|
|
@@ -273,7 +285,7 @@ function createOutRequest() {
|
|
|
273
285
|
if (conn && conn.remoteName && !conn.closing) {
|
|
274
286
|
self.forwardTo(conn);
|
|
275
287
|
} else {
|
|
276
|
-
self.peer.waitForIdentified(self.boundOnIdentified);
|
|
288
|
+
self.waitForIdentSlot = self.peer.waitForIdentified(self.boundOnIdentified);
|
|
277
289
|
}
|
|
278
290
|
};
|
|
279
291
|
|
|
@@ -433,6 +445,8 @@ function onError(err) {
|
|
|
433
445
|
}));
|
|
434
446
|
|
|
435
447
|
self.reqContFrames.length = 0;
|
|
448
|
+
|
|
449
|
+
self.free();
|
|
436
450
|
};
|
|
437
451
|
|
|
438
452
|
LazyRelayInReq.prototype.sendErrorFrame =
|
|
@@ -698,7 +712,14 @@ function emitError(err) {
|
|
|
698
712
|
self.inreq.circuit.state.onRequestError(err);
|
|
699
713
|
}
|
|
700
714
|
|
|
701
|
-
|
|
715
|
+
// We need to defer the inreq onError work, because we might be
|
|
716
|
+
// *syncronously* processing an error after an attempt to write to a
|
|
717
|
+
// socket. Otherwise, we might end up freeing the in/outreq pair before a
|
|
718
|
+
// handleFrameLazily has completed.
|
|
719
|
+
process.nextTick(deferInReqOnError);
|
|
720
|
+
function deferInReqOnError() {
|
|
721
|
+
self.inreq.onError(err);
|
|
722
|
+
}
|
|
702
723
|
};
|
|
703
724
|
|
|
704
725
|
LazyRelayOutReq.prototype.logError =
|
package/lib/object_pool.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
23
|
var assert = require('assert');
|
|
24
|
+
var stat = require('../stat-tags');
|
|
24
25
|
|
|
25
26
|
var DEFAULT_MAX_SIZE = 1000;
|
|
26
27
|
|
|
@@ -42,16 +43,28 @@ function ObjectPool(options) {
|
|
|
42
43
|
|
|
43
44
|
this.freeList = [];
|
|
44
45
|
this.outstanding = 0;
|
|
45
|
-
|
|
46
|
-
this.
|
|
46
|
+
|
|
47
|
+
this.freeListStatTags = new stat.ObjectPoolTags(
|
|
48
|
+
this.name,
|
|
49
|
+
'free'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
this.outstandingStatTags = new stat.ObjectPoolTags(
|
|
53
|
+
this.name,
|
|
54
|
+
'outstanding'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// only used in debug mode
|
|
58
|
+
this.outstandingList = [];
|
|
47
59
|
}
|
|
48
60
|
|
|
49
|
-
ObjectPool.
|
|
61
|
+
ObjectPool.channel = null;
|
|
50
62
|
ObjectPool.reportInterval = null;
|
|
51
63
|
ObjectPool.timers = null;
|
|
52
64
|
ObjectPool.pools = [];
|
|
53
65
|
ObjectPool.timer = null;
|
|
54
66
|
ObjectPool.refs = 0;
|
|
67
|
+
ObjectPool.debug = false;
|
|
55
68
|
|
|
56
69
|
ObjectPool.setup = function setup(options) {
|
|
57
70
|
var pool = new ObjectPool(options);
|
|
@@ -82,11 +95,11 @@ ObjectPool.bootstrap = function bootstrap(options) {
|
|
|
82
95
|
assert(typeof options === 'object', 'expected options object');
|
|
83
96
|
|
|
84
97
|
assert(
|
|
85
|
-
typeof options.
|
|
86
|
-
typeof options.
|
|
87
|
-
'expected options.
|
|
98
|
+
typeof options.channel === 'object' &&
|
|
99
|
+
typeof options.channel.emitFastStat === 'function',
|
|
100
|
+
'expected options.channel to be TChannel instance'
|
|
88
101
|
);
|
|
89
|
-
ObjectPool.
|
|
102
|
+
ObjectPool.channel = options.channel;
|
|
90
103
|
|
|
91
104
|
assert(
|
|
92
105
|
typeof options.reportInterval === 'number',
|
|
@@ -101,6 +114,10 @@ ObjectPool.bootstrap = function bootstrap(options) {
|
|
|
101
114
|
);
|
|
102
115
|
ObjectPool.timers = options.timers;
|
|
103
116
|
|
|
117
|
+
if (typeof options.debug === 'boolean') {
|
|
118
|
+
ObjectPool.debug = options.debug;
|
|
119
|
+
}
|
|
120
|
+
|
|
104
121
|
ObjectPool.timer = ObjectPool.timers.setTimeout(
|
|
105
122
|
ObjectPool.reportStats,
|
|
106
123
|
ObjectPool.reportInterval
|
|
@@ -120,7 +137,7 @@ ObjectPool.reportStats = function reportStats() {
|
|
|
120
137
|
|
|
121
138
|
var i;
|
|
122
139
|
for (i = 0; i < ObjectPool.pools.length; i++) {
|
|
123
|
-
ObjectPool.pools[i].reportStats(ObjectPool.
|
|
140
|
+
ObjectPool.pools[i].reportStats(ObjectPool.channel);
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
ObjectPool.timer = ObjectPool.timers.setTimeout(
|
|
@@ -129,16 +146,19 @@ ObjectPool.reportStats = function reportStats() {
|
|
|
129
146
|
);
|
|
130
147
|
};
|
|
131
148
|
|
|
132
|
-
ObjectPool.prototype.reportStats = function reportStats(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
149
|
+
ObjectPool.prototype.reportStats = function reportStats(channel) {
|
|
150
|
+
channel.emitFastStat(
|
|
151
|
+
'tchannel.object-pool',
|
|
152
|
+
'gauge',
|
|
153
|
+
this.freeList.length,
|
|
154
|
+
this.freeListStatTags
|
|
136
155
|
);
|
|
137
156
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
this.outstanding
|
|
157
|
+
channel.emitFastStat(
|
|
158
|
+
'tchannel.object-pool',
|
|
159
|
+
'gauge',
|
|
160
|
+
this.outstanding,
|
|
161
|
+
this.outstandingStatTags
|
|
142
162
|
);
|
|
143
163
|
};
|
|
144
164
|
|
|
@@ -149,10 +169,20 @@ ObjectPool.prototype.get = function get() {
|
|
|
149
169
|
inst = this.freeList.pop();
|
|
150
170
|
assert(inst._objectPoolIsFreed, 'instance retreived from pool is free');
|
|
151
171
|
inst._objectPoolIsFreed = false;
|
|
172
|
+
|
|
173
|
+
if (ObjectPool.debug) {
|
|
174
|
+
this.outstandingList.push(inst);
|
|
175
|
+
}
|
|
176
|
+
|
|
152
177
|
return inst;
|
|
153
178
|
} else {
|
|
154
179
|
inst = new this.Type();
|
|
155
180
|
inst._objectPoolIsFreed = false;
|
|
181
|
+
|
|
182
|
+
if (ObjectPool.debug) {
|
|
183
|
+
this.outstandingList.push(inst);
|
|
184
|
+
}
|
|
185
|
+
|
|
156
186
|
return inst;
|
|
157
187
|
}
|
|
158
188
|
};
|
|
@@ -166,4 +196,14 @@ ObjectPool.prototype.free = function free(inst) {
|
|
|
166
196
|
this.freeList.push(inst);
|
|
167
197
|
}
|
|
168
198
|
this.outstanding -= 1;
|
|
199
|
+
|
|
200
|
+
var i;
|
|
201
|
+
if (ObjectPool.debug) {
|
|
202
|
+
for (i = 0; i < this.outstandingList.length; i++) {
|
|
203
|
+
if (this.outstandingList[i] === inst) {
|
|
204
|
+
this.outstandingList.splice(i, 1);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
169
209
|
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "tchannel",
|
|
3
3
|
"description": "network multiplexing and framing protocol for RPC or parser drag racing",
|
|
4
4
|
"author": "mranney@uber.com",
|
|
5
|
-
"version": "3.6.
|
|
5
|
+
"version": "3.6.18",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"lint": "eslint $(git ls-files | grep '.js$')",
|
|
8
8
|
"travis": "npm run test",
|
package/peer.js
CHANGED
|
@@ -36,6 +36,7 @@ var NoPreference = require('./peer_score_strategies.js').NoPreference;
|
|
|
36
36
|
var PreferIncoming = require('./peer_score_strategies.js').PreferIncoming;
|
|
37
37
|
var Range = require('./range');
|
|
38
38
|
var PeerDrain = require('./drain.js').PeerDrain;
|
|
39
|
+
var ObjectPool = require('./lib/object_pool');
|
|
39
40
|
|
|
40
41
|
var DEFAULT_REPORT_INTERVAL = 1000;
|
|
41
42
|
|
|
@@ -65,6 +66,8 @@ function TChannelPeer(channel, hostPort, options) {
|
|
|
65
66
|
this.boundOnPendingChange = onPendingChange;
|
|
66
67
|
this.scoreRange = null;
|
|
67
68
|
|
|
69
|
+
this.waitForIdentifiedListeners = [];
|
|
70
|
+
|
|
68
71
|
this.reportInterval = options.reportInterval || DEFAULT_REPORT_INTERVAL;
|
|
69
72
|
if (this.reportInterval > 0 && this.channel.emitConnectionMetrics) {
|
|
70
73
|
this.reportTimer = this.timers.setTimeout(
|
|
@@ -419,20 +422,35 @@ function waitForIdentified(conn, callback) {
|
|
|
419
422
|
} else if (conn.remoteName) {
|
|
420
423
|
callback(null);
|
|
421
424
|
} else {
|
|
422
|
-
self._waitForIdentified(conn, callback);
|
|
425
|
+
return self._waitForIdentified(conn, callback);
|
|
423
426
|
}
|
|
427
|
+
|
|
428
|
+
return -1;
|
|
424
429
|
};
|
|
425
430
|
|
|
426
431
|
TChannelPeer.prototype._waitForIdentified =
|
|
427
432
|
function _waitForIdentified(conn, callback) {
|
|
428
433
|
var self = this;
|
|
429
434
|
|
|
435
|
+
// Setup an ident descriptor so we can stop waiting for identified later
|
|
436
|
+
var slot = self.getIdentDescriptorSlot();
|
|
437
|
+
var descriptor = WaitForIdentifiedDescriptor.alloc();
|
|
438
|
+
descriptor.reset(
|
|
439
|
+
onConnectionClose,
|
|
440
|
+
onConnectionError,
|
|
441
|
+
onIdentified,
|
|
442
|
+
conn
|
|
443
|
+
);
|
|
444
|
+
self.waitForIdentifiedListeners[slot] = descriptor;
|
|
445
|
+
|
|
430
446
|
self.pendingIdentified++;
|
|
431
447
|
conn.errorEvent.on(onConnectionError);
|
|
432
448
|
conn.closeEvent.on(onConnectionClose);
|
|
433
449
|
conn.identifiedEvent.on(onIdentified);
|
|
434
450
|
self.invalidateScore('waitForIdentified');
|
|
435
451
|
|
|
452
|
+
return slot;
|
|
453
|
+
|
|
436
454
|
function onConnectionError(err) {
|
|
437
455
|
finish(err);
|
|
438
456
|
}
|
|
@@ -446,15 +464,45 @@ function _waitForIdentified(conn, callback) {
|
|
|
446
464
|
}
|
|
447
465
|
|
|
448
466
|
function finish(err) {
|
|
449
|
-
self.
|
|
450
|
-
conn.errorEvent.removeListener(onConnectionError);
|
|
451
|
-
conn.closeEvent.removeListener(onConnectionClose);
|
|
452
|
-
conn.identifiedEvent.removeListener(onIdentified);
|
|
453
|
-
self.invalidateScore('waitForIdentified > finish');
|
|
467
|
+
self.stopWaitingForIdentified(slot);
|
|
454
468
|
callback(err);
|
|
455
469
|
}
|
|
456
470
|
};
|
|
457
471
|
|
|
472
|
+
TChannelPeer.prototype.stopWaitingForIdentified =
|
|
473
|
+
function stopWaitingForIdentified(slot) {
|
|
474
|
+
assert(typeof slot === 'number', 'stopWaitingForIdentified arg1 should be number');
|
|
475
|
+
|
|
476
|
+
if (slot === -1) {
|
|
477
|
+
// when connection was already identified, `waitForIdentified` will
|
|
478
|
+
// return -1
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
var descriptor = this.waitForIdentifiedListeners[slot];
|
|
483
|
+
this.waitForIdentifiedListeners[slot] = null;
|
|
484
|
+
var conn = descriptor.conn;
|
|
485
|
+
|
|
486
|
+
conn.errorEvent.removeListener(descriptor.error);
|
|
487
|
+
conn.closeEvent.removeListener(descriptor.close);
|
|
488
|
+
conn.identifiedEvent.removeListener(descriptor.ident);
|
|
489
|
+
this.pendingIdentified = 0;
|
|
490
|
+
this.invalidateScore('waitForIdentified > finish');
|
|
491
|
+
|
|
492
|
+
descriptor.free();
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
TChannelPeer.prototype.getIdentDescriptorSlot =
|
|
496
|
+
function getIdentDescriptorSlot() {
|
|
497
|
+
var i;
|
|
498
|
+
for (i = 0; i < this.waitForIdentifiedListeners.length; i++) {
|
|
499
|
+
if (this.waitForIdentifiedListeners[i] === null) {
|
|
500
|
+
return i;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return this.waitForIdentifiedListeners.length;
|
|
504
|
+
};
|
|
505
|
+
|
|
458
506
|
TChannelPeer.prototype.request = function peerRequest(options) {
|
|
459
507
|
var self = this;
|
|
460
508
|
options.timeout = options.timeout || Request.defaultTimeout;
|
|
@@ -677,3 +725,28 @@ TChannelPeer.prototype.getScore = function getScore() {
|
|
|
677
725
|
};
|
|
678
726
|
|
|
679
727
|
module.exports = TChannelPeer;
|
|
728
|
+
|
|
729
|
+
function WaitForIdentifiedDescriptor(close, error, ident, conn) {
|
|
730
|
+
this.close = null;
|
|
731
|
+
this.error = null;
|
|
732
|
+
this.ident = null;
|
|
733
|
+
this.conn = null;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
WaitForIdentifiedDescriptor.prototype.reset =
|
|
737
|
+
function reset(close, error, ident, conn) {
|
|
738
|
+
this.close = close;
|
|
739
|
+
this.error = error;
|
|
740
|
+
this.ident = ident;
|
|
741
|
+
this.conn = conn;
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
WaitForIdentifiedDescriptor.prototype.clear =
|
|
745
|
+
function clear() {
|
|
746
|
+
this.close = null;
|
|
747
|
+
this.error = null;
|
|
748
|
+
this.ident = null;
|
|
749
|
+
this.conn = null;
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
ObjectPool.setup({Type: WaitForIdentifiedDescriptor, maxSize: 100});
|
package/relay_handler.js
CHANGED
|
@@ -59,6 +59,7 @@ RelayHandler.prototype.handleLazily = function handleLazily(conn, reqFrame) {
|
|
|
59
59
|
if (!rereq.peer) {
|
|
60
60
|
rereq.sendErrorFrame('Declined', 'no peer available for request');
|
|
61
61
|
self.logger.info('no relay peer available', rereq.extendLogInfo({}));
|
|
62
|
+
rereq.free();
|
|
62
63
|
return true;
|
|
63
64
|
}
|
|
64
65
|
|
package/stat-tags.js
CHANGED
|
@@ -58,7 +58,8 @@ module.exports = {
|
|
|
58
58
|
ConnectionsErrorsTags: ConnectionsErrorsTags,
|
|
59
59
|
ConnectionsClosedTags: ConnectionsClosedTags,
|
|
60
60
|
RelayLatencyTags: RelayLatencyTags,
|
|
61
|
-
HTTPHanlderBuildLatencyTags: HTTPHanlderBuildLatencyTags
|
|
61
|
+
HTTPHanlderBuildLatencyTags: HTTPHanlderBuildLatencyTags,
|
|
62
|
+
ObjectPoolTags: ObjectPoolTags
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
function InboundCallsRecvdTags(cn, serviceName, endpoint) {
|
|
@@ -663,3 +664,25 @@ HTTPHanlderBuildLatencyTags.prototype.toStatKey = function toStatKey(prefix) {
|
|
|
663
664
|
clean(this.targetService, 'no-target-service') + '.' +
|
|
664
665
|
(this.streamed ? 'streamed' : 'unstreamed');
|
|
665
666
|
};
|
|
667
|
+
|
|
668
|
+
function ObjectPoolTags(poolName, statType) {
|
|
669
|
+
this.app = '';
|
|
670
|
+
this.host = '';
|
|
671
|
+
this.cluster = '';
|
|
672
|
+
this.version = '';
|
|
673
|
+
|
|
674
|
+
this.poolName = poolName;
|
|
675
|
+
this.statType = statType;
|
|
676
|
+
|
|
677
|
+
this._cachedPrefix = '';
|
|
678
|
+
this._key = '';
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
ObjectPoolTags.prototype.toStatKey = function toStatKey(prefix) {
|
|
682
|
+
// prefix should never change but we store it in _cachedPrefix just in case
|
|
683
|
+
if (!this._key || prefix !== this._cachedPrefix) {
|
|
684
|
+
this._key = prefix + '.' + this.poolName + '.' + this.statType;
|
|
685
|
+
this._cachedPrefix = prefix;
|
|
686
|
+
}
|
|
687
|
+
return this._key;
|
|
688
|
+
};
|
|
@@ -29,6 +29,7 @@ var debugLogtron = require('debug-logtron');
|
|
|
29
29
|
|
|
30
30
|
var TChannel = require('../../channel.js');
|
|
31
31
|
var CollapsedAssert = require('./collapsed-assert.js');
|
|
32
|
+
var ObjectPool = require('../../lib/object_pool');
|
|
32
33
|
|
|
33
34
|
var loadConfig = require('./load_config.js');
|
|
34
35
|
|
|
@@ -77,7 +78,8 @@ function allocCluster(opts) {
|
|
|
77
78
|
var channelOptions = extend({
|
|
78
79
|
logger: logger,
|
|
79
80
|
timeoutFuzz: 0,
|
|
80
|
-
traceSample: 1
|
|
81
|
+
traceSample: 1,
|
|
82
|
+
objectPoolDebug: true
|
|
81
83
|
}, defaultChannelOptions, opts.channelOptions || opts);
|
|
82
84
|
|
|
83
85
|
for (var i = 0; i < opts.numPeers; i++) {
|
|
@@ -217,6 +219,8 @@ function clusterTester(opts, t) {
|
|
|
217
219
|
|
|
218
220
|
cluster.assertEmptyState(collapsedAssert);
|
|
219
221
|
collapsedAssert.report(assert, 'cluster has an empty state');
|
|
222
|
+
|
|
223
|
+
checkObjectPools(assert);
|
|
220
224
|
}
|
|
221
225
|
cluster.destroy();
|
|
222
226
|
});
|
|
@@ -225,6 +229,24 @@ function clusterTester(opts, t) {
|
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
|
|
232
|
+
function checkObjectPools(assert) {
|
|
233
|
+
var i;
|
|
234
|
+
var pool;
|
|
235
|
+
var length;
|
|
236
|
+
for (i = 0; i < ObjectPool.pools.length; i++) {
|
|
237
|
+
pool = ObjectPool.pools[i];
|
|
238
|
+
length = pool.outstandingList.length;
|
|
239
|
+
assert.ok(
|
|
240
|
+
length === 0,
|
|
241
|
+
'expected object pool ' + pool.name + ' to have no outstanding ' +
|
|
242
|
+
'instances, found ' + length + ' instances'
|
|
243
|
+
);
|
|
244
|
+
if (length) {
|
|
245
|
+
assert.comment(util.inspect(pool.outstandingList));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
228
250
|
allocCluster.test = function testCluster(desc, opts, t) {
|
|
229
251
|
if (opts === undefined) {
|
|
230
252
|
return test(desc);
|
package/test/object_pool.js
CHANGED
|
@@ -47,10 +47,14 @@ ObjectPool.setup({
|
|
|
47
47
|
test('object pool happy', function t1(assert) {
|
|
48
48
|
var timers = Timer(0);
|
|
49
49
|
var stats = {};
|
|
50
|
-
var
|
|
50
|
+
var channel = {emitFastStat: fakeEmitFastStat};
|
|
51
|
+
|
|
52
|
+
function fakeEmitFastStat(name, type, val, tags) {
|
|
53
|
+
stats[name + tags.toStatKey('')] = val;
|
|
54
|
+
}
|
|
51
55
|
|
|
52
56
|
ObjectPool.bootstrap({
|
|
53
|
-
|
|
57
|
+
channel: channel,
|
|
54
58
|
timers: timers,
|
|
55
59
|
reportInterval: 500
|
|
56
60
|
});
|
|
@@ -89,8 +93,8 @@ test('object pool happy', function t1(assert) {
|
|
|
89
93
|
assert.equal(pool.outstanding, 1, '1 outstanding instace');
|
|
90
94
|
|
|
91
95
|
timers.advance(500);
|
|
92
|
-
assert.equal(stats['object-
|
|
93
|
-
assert.equal(stats['object-
|
|
96
|
+
assert.equal(stats['tchannel.object-pool.Widget.free'], 1);
|
|
97
|
+
assert.equal(stats['tchannel.object-pool.Widget.outstanding'], 1);
|
|
94
98
|
|
|
95
99
|
w = Widget.alloc();
|
|
96
100
|
|
|
@@ -108,8 +112,8 @@ test('object pool happy', function t1(assert) {
|
|
|
108
112
|
assert.equal(pool.outstanding, 0, '0 outstanding instace');
|
|
109
113
|
|
|
110
114
|
timers.advance(500);
|
|
111
|
-
assert.equal(stats['object-
|
|
112
|
-
assert.equal(stats['object-
|
|
115
|
+
assert.equal(stats['tchannel.object-pool.Widget.free'], 2);
|
|
116
|
+
assert.equal(stats['tchannel.object-pool.Widget.outstanding'], 0);
|
|
113
117
|
|
|
114
118
|
assert.end();
|
|
115
119
|
});
|
package/test/relay_lazy.js
CHANGED
|
@@ -301,6 +301,7 @@ allocCluster.test('lazy relay request times out', {
|
|
|
301
301
|
|
|
302
302
|
var relayOutPeer = relayChan.peers.get(dest.hostPort);
|
|
303
303
|
relayOutPeer.waitForIdentified = function punchWaitForIdentified() {
|
|
304
|
+
return -1;
|
|
304
305
|
};
|
|
305
306
|
|
|
306
307
|
sourceChan.request({
|
|
@@ -442,7 +443,7 @@ allocCluster.test('relay request handles channel close correctly', {
|
|
|
442
443
|
'tchannel.connection.reset',
|
|
443
444
|
'expected connection error');
|
|
444
445
|
assert.notOk(res, 'expected no response');
|
|
445
|
-
finish
|
|
446
|
+
process.nextTick(finish);
|
|
446
447
|
}
|
|
447
448
|
|
|
448
449
|
function finish() {
|