Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

changed the get_node strategy when keep-alive is enabled

  • Loading branch information...
commit 418b3bc4f24a7d6e05e373675861dac6f464e694 1 parent 13a5a88
Danny Coates authored January 11, 2013
15  lib/endpoint.js
@@ -30,6 +30,7 @@ module.exports = function (inherits, EventEmitter, Pinger) {
30 30
 		this.healthy = true
31 31
 		this.name = this.ip + ':' + this.port
32 32
 		this.address = this.ip
  33
+		this.keepAlive = options.keepAlive
33 34
 
34 35
 		this.pinger = new Pinger(this.ping.bind(this))
35 36
 		this.pinger.on('pong', function () {
@@ -38,7 +39,7 @@ module.exports = function (inherits, EventEmitter, Pinger) {
38 39
 
39 40
 		this.pingPath = options.ping
40 41
 		this.pingTimeout = options.pingTimeout || 2000
41  
-		if (options.keepAlive) {
  42
+		if (this.keepAlive) {
42 43
 			if (protocol === http) {
43 44
 				this.agent = new KeepAlive(options.agentOptions)
44 45
 			}
@@ -72,6 +73,18 @@ module.exports = function (inherits, EventEmitter, Pinger) {
72 73
 	}
73 74
 	inherits(Endpoint, EventEmitter)
74 75
 
  76
+	Endpoint.prototype.connected = function () {
  77
+		return this.agent.sockets[this.name] && this.agent.sockets[this.name].length
  78
+	}
  79
+
  80
+	Endpoint.prototype.ready = function () {
  81
+		return this.healthy
  82
+			&& (this.keepAlive ?
  83
+				this.connected() > this.pending :
  84
+				this.pending === 0
  85
+			)
  86
+	}
  87
+
75 88
 	Endpoint.prototype.stats = function () {
76 89
 		var socketNames = Object.keys(this.agent.sockets)
77 90
 		var requestCounts = []
32  lib/pool.js
@@ -79,6 +79,7 @@ module.exports = function (inherits, EventEmitter, Endpoint, RequestSet) {
79 79
 		}
80 80
 		return healthy
81 81
 	}
  82
+	Pool.prototype.healthyNodes = Pool.prototype.healthy_nodes
82 83
 
83 84
 	Pool.prototype.onRetry = function (err) {
84 85
 		this.emit('retrying', err)
@@ -171,34 +172,37 @@ module.exports = function (inherits, EventEmitter, Endpoint, RequestSet) {
171 172
 
172 173
 	Pool.prototype.get_node = function () {
173 174
 		var len = this.nodes.length
174  
-		var h = 0
  175
+		var h = []
175 176
 		var sum = 0
176 177
 		var totalPending = 0
  178
+		var r = Math.floor(Math.random() * len)
177 179
 		for (var i = 0; i < len; i++) {
178  
-			var node = this.nodes[i]
179  
-			if (node.healthy) {
180  
-				h++
181  
-				sum += node.busyness()
  180
+			r = (r + 1) % len
  181
+			var node = this.nodes[r]
  182
+			if (node.ready()) {
  183
+				return node //fast path
  184
+			}
  185
+			else if (node.healthy) {
  186
+				h.push(node)
  187
+				sum += node.pending
182 188
 			}
183 189
 			totalPending += node.pending
184 190
 		}
185 191
 		if (totalPending >= this.maxPending) {
186 192
 			return Endpoint.overloaded()
187 193
 		}
188  
-		if (h !== 0) {
189  
-			var avg = sum / h
190  
-			var r = Math.floor(Math.random() * len)
191  
-			for (i = 0; i < len; i++) {
192  
-				r = (r + 1) % len
193  
-				node = this.nodes[r]
194  
-				if (node.healthy && avg >= node.busyness()) {
195  
-					return node
196  
-				}
  194
+		var avg = sum / h.length
  195
+		while (h.length) {
  196
+			var node = h.pop()
  197
+			if (node.pending <= avg) {
  198
+				return node
197 199
 			}
198 200
 		}
199 201
 		return Endpoint.unhealthy()
200 202
 	}
201 203
 
  204
+	Pool.prototype.getNode = Pool.prototype.get_node //must keep the old _ api
  205
+
202 206
 	Pool.prototype.pending = function () {
203 207
 		return this.nodes.reduce(function (a, b) { return a + b.pending }, 0)
204 208
 	}
42  test/endpoint_test.js
@@ -442,6 +442,48 @@ describe("Endpoint", function () {
442 442
 	})
443 443
 
444 444
 	//
  445
+	// ready
  446
+	//
  447
+	//////////////////////////////////////////////////////////////////////////////
  448
+
  449
+	describe("ready()", function () {
  450
+
  451
+		it('returns true when it is healthy and connected > pending with keepAlive on',
  452
+			function () {
  453
+				var e = new Endpoint(http, '127.0.0.1', 6969, {keepAlive: true})
  454
+				e.pending = 1
  455
+				e.agent.sockets[e.name] = [1,2]
  456
+				assert(e.ready())
  457
+			}
  458
+		)
  459
+
  460
+		it('returns false when it is healthy and connected = pending with keepAlive on',
  461
+			function () {
  462
+				var e = new Endpoint(http, '127.0.0.1', 6969, {keepAlive: true})
  463
+				e.pending = 1
  464
+				e.agent.sockets[e.name] = [1]
  465
+				assert(!e.ready())
  466
+			}
  467
+		)
  468
+
  469
+		it('returns true when it is healthy and pending = 0 with keepAlive off',
  470
+			function () {
  471
+				var e = new Endpoint(http, '127.0.0.1', 6969)
  472
+				e.pending = 0
  473
+				assert(e.ready())
  474
+			}
  475
+		)
  476
+
  477
+		it('returns false when it is healthy and pending > 0 with keepAlive off',
  478
+			function () {
  479
+				var e = new Endpoint(http, '127.0.0.1', 6969)
  480
+				e.pending = 1
  481
+				assert(!e.ready())
  482
+			}
  483
+		)
  484
+	})
  485
+
  486
+	//
445 487
 	// setHealthy
446 488
 	//
447 489
 	//////////////////////////////////////////////////////////////////////////////
18  test/pool_test.js
@@ -11,7 +11,10 @@ var http = {
11 11
 
12 12
 function FakeEndpoint() {}
13 13
 inherits(FakeEndpoint, EventEmitter)
  14
+FakeEndpoint.prototype.pending = 1
14 15
 FakeEndpoint.prototype.busyness = function () { return 1 }
  16
+FakeEndpoint.prototype.connected = function () { return 0 }
  17
+FakeEndpoint.prototype.ready = function () { return false }
15 18
 var overloaded = new FakeEndpoint()
16 19
 FakeEndpoint.overloaded = function () { return overloaded }
17 20
 var unhealthy = new FakeEndpoint()
@@ -106,6 +109,21 @@ describe('Pool', function () {
106 109
 			p.nodes.forEach(function (n) { n.healthy = false })
107 110
 			assert.equal(p.get_node(), unhealthy)
108 111
 		})
  112
+
  113
+		it('returns a "ready" node when one is available', function () {
  114
+			var p = new Pool(http, ['127.0.0.1:8080', '127.0.0.1:8081', '127.0.0.1:8082'])
  115
+			var n = p.nodes[0]
  116
+			n.ready = function () { return true }
  117
+			assert.equal(p.get_node(), n);
  118
+		})
  119
+
  120
+		it('returns a healthy node when none are "ready"', function () {
  121
+			var p = new Pool(http, ['127.0.0.1:8080', '127.0.0.1:8081', '127.0.0.1:8082'])
  122
+			p.nodes[0].healthy = false
  123
+			p.nodes[1].healthy = false
  124
+			p.nodes[2].healthy = true
  125
+			assert(p.get_node().healthy);
  126
+		})
109 127
 	})
110 128
 
111 129
 	//

0 notes on commit 418b3bc

Please sign in to comment.
Something went wrong with that request. Please try again.