radar_client
Advanced tools
Comparing version 0.15.4 to 0.16.0
@@ -0,1 +1,4 @@ | ||
### 0.16.0 | ||
* [PR #74](https://github.com/zendesk/radar_client/pull/74) - Add a random splay while backing off, also expose backoff events. | ||
### 0.15.4 | ||
@@ -2,0 +5,0 @@ * [PR #71](https://github.com/zendesk/radar_client/pull/71) - Second try: flexible minor, patch specifier for radar_message dependency |
@@ -46,3 +46,3 @@ var RadarClient = | ||
/* 0 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -61,5 +61,5 @@ var Client = __webpack_require__(1) | ||
/***/ }, | ||
/***/ }), | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -451,2 +451,6 @@ /* globals setImmediate */ | ||
}) | ||
manager.on('backoff', function (time, step) { | ||
self.emit('backoff', time, step) | ||
}) | ||
} | ||
@@ -608,5 +612,5 @@ | ||
/***/ }, | ||
/***/ }), | ||
/* 2 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
@@ -631,2 +635,5 @@ function M() { this._events = {}; } | ||
}, | ||
listeners: function(ev) { | ||
return (this._events ? this._events[ev] || [] : []); | ||
}, | ||
emit: function(ev) { | ||
@@ -663,11 +670,11 @@ this._events || (this._events = {}); | ||
/***/ }, | ||
/***/ }), | ||
/* 3 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
module.exports = eio; | ||
/***/ }, | ||
/***/ }), | ||
/* 4 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
@@ -702,5 +709,5 @@ function Scope (typeName, scope, client) { | ||
/***/ }, | ||
/***/ }), | ||
/* 5 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -735,4 +742,3 @@ var log = __webpack_require__(6)('radar_state') | ||
onevent: function (event, from, to) { | ||
log.debug('before-' + event + ', from: ' + from + ', to: ' + to, | ||
Array.prototype.slice.call(arguments)) | ||
log.debug('from ' + from + ' -> ' + to + ', event: ' + event) | ||
@@ -744,5 +750,2 @@ this.emit('event', event) | ||
onstate: function (event, from, to) { | ||
log.debug('event-state-' + event + ', from: ' + from + ', to: ' + to, | ||
Array.prototype.slice.call(arguments)) | ||
this.emit('enterState', to) | ||
@@ -767,4 +770,2 @@ this.emit(to, arguments) | ||
ondisconnected: function (event, from, to) { | ||
backoff.increment() | ||
if (this._timer) { | ||
@@ -776,3 +777,7 @@ clearTimeout(this._timer) | ||
var time = backoff.get() | ||
backoff.increment() | ||
this.emit('backoff', time, backoff.failures) | ||
log.debug('reconnecting in ' + time + 'msec') | ||
this._timer = setTimeout(function () { | ||
@@ -850,11 +855,11 @@ delete machine._timer | ||
/***/ }, | ||
/***/ }), | ||
/* 6 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
module.exports = Minilog; | ||
/***/ }, | ||
/***/ }), | ||
/* 7 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
@@ -867,5 +872,7 @@ function Backoff () { | ||
Backoff.fallback = 60000 | ||
Backoff.maxSplay = 5000 | ||
Backoff.prototype.get = function () { | ||
return Backoff.durations[this.failures] || Backoff.fallback | ||
var splay = Math.ceil(Math.random() * Backoff.maxSplay) | ||
return splay + (Backoff.durations[this.failures] || Backoff.fallback) | ||
} | ||
@@ -888,5 +895,5 @@ | ||
/***/ }, | ||
/***/ }), | ||
/* 8 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
@@ -1084,9 +1091,9 @@ /* | ||
/***/ }, | ||
/***/ }), | ||
/* 9 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
// Auto-generated file, overwritten by scripts/add_package_version.js | ||
function getClientVersion () { return '0.15.4' } | ||
function getClientVersion () { return '0.16.0' } | ||
@@ -1096,5 +1103,5 @@ module.exports = getClientVersion | ||
/***/ }, | ||
/***/ }), | ||
/* 10 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -1113,5 +1120,5 @@ var Request = __webpack_require__(11), | ||
/***/ }, | ||
/***/ }), | ||
/* 11 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -1296,5 +1303,5 @@ var logger = __webpack_require__(6)('message:request'); | ||
/***/ }, | ||
/***/ }), | ||
/* 12 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -1379,5 +1386,5 @@ var logger = __webpack_require__(6)('message:response'); | ||
/***/ }, | ||
/***/ }), | ||
/* 13 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports) { | ||
@@ -1412,3 +1419,3 @@ function Batch () { | ||
/***/ } | ||
/***/ }) | ||
/******/ ]); |
@@ -7,5 +7,7 @@ function Backoff () { | ||
Backoff.fallback = 60000 | ||
Backoff.maxSplay = 5000 | ||
Backoff.prototype.get = function () { | ||
return Backoff.durations[this.failures] || Backoff.fallback | ||
var splay = Math.ceil(Math.random() * Backoff.maxSplay) | ||
return splay + (Backoff.durations[this.failures] || Backoff.fallback) | ||
} | ||
@@ -12,0 +14,0 @@ |
// Auto-generated file, overwritten by scripts/add_package_version.js | ||
function getClientVersion () { return '0.15.4' } | ||
function getClientVersion () { return '0.16.0' } | ||
module.exports = getClientVersion |
@@ -386,2 +386,6 @@ /* globals setImmediate */ | ||
}) | ||
manager.on('backoff', function (time, step) { | ||
self.emit('backoff', time, step) | ||
}) | ||
} | ||
@@ -388,0 +392,0 @@ |
@@ -29,4 +29,3 @@ var log = require('minilog')('radar_state') | ||
onevent: function (event, from, to) { | ||
log.debug('before-' + event + ', from: ' + from + ', to: ' + to, | ||
Array.prototype.slice.call(arguments)) | ||
log.debug('from ' + from + ' -> ' + to + ', event: ' + event) | ||
@@ -38,5 +37,2 @@ this.emit('event', event) | ||
onstate: function (event, from, to) { | ||
log.debug('event-state-' + event + ', from: ' + from + ', to: ' + to, | ||
Array.prototype.slice.call(arguments)) | ||
this.emit('enterState', to) | ||
@@ -61,4 +57,2 @@ this.emit(to, arguments) | ||
ondisconnected: function (event, from, to) { | ||
backoff.increment() | ||
if (this._timer) { | ||
@@ -70,3 +64,7 @@ clearTimeout(this._timer) | ||
var time = backoff.get() | ||
backoff.increment() | ||
this.emit('backoff', time, backoff.failures) | ||
log.debug('reconnecting in ' + time + 'msec') | ||
this._timer = setTimeout(function () { | ||
@@ -73,0 +71,0 @@ delete machine._timer |
{ | ||
"name": "radar_client", | ||
"description": "Realtime apps with a high level API based on engine.io", | ||
"version": "0.15.4", | ||
"version": "0.16.0", | ||
"license": "Apache-2.0", | ||
@@ -6,0 +6,0 @@ "author": "Zendesk, Inc.", |
@@ -23,3 +23,5 @@ var assert = require('assert') | ||
Backoff.durations.forEach(function (duration) { | ||
assert.equal(duration, b.get()) | ||
var v = b.get() | ||
assert(duration <= v) | ||
assert(duration + Backoff.maxSplay > v) | ||
b.increment() | ||
@@ -32,7 +34,8 @@ }) | ||
var b = this.b | ||
assert.equal(b.get(), 1000) | ||
assert(b.get() >= 1000) | ||
b.increment() | ||
assert.ok(b.get() > 1000) | ||
assert(b.get() >= 2000) | ||
b.success() | ||
assert.equal(b.get(), 1000) | ||
var v = b.get() | ||
assert(v >= 1000 && v < 6000) | ||
done() | ||
@@ -50,3 +53,3 @@ }, | ||
b.increment() | ||
assert.equal(b.get(), 60000) | ||
assert(b.get() > 60000) | ||
done() | ||
@@ -53,0 +56,0 @@ } |
@@ -54,4 +54,10 @@ var assert = require('assert') | ||
}, 10) | ||
}, | ||
'forwards backoff events from manager': function (done) { | ||
this.client.once('backoff', function (time, step) { | ||
done() | ||
}) | ||
this.client.manager.emit('backoff', 10, 1) | ||
} | ||
} | ||
@@ -58,0 +64,0 @@ |
@@ -5,2 +5,3 @@ var assert = require('assert') | ||
var Response = require('radar_message').Response | ||
var Backoff = require('../lib/backoff.js') | ||
var client | ||
@@ -10,2 +11,5 @@ | ||
before: function (done) { | ||
// speed up some tests | ||
Backoff.maxSplay = 100 | ||
Backoff.durations = [ 100, 200, 400 ] | ||
RadarClient.setBackend(MockEngine) | ||
@@ -109,3 +113,2 @@ done() | ||
'should resend queued presences': function (done) { | ||
this.timeout(4000) | ||
var connected = false | ||
@@ -139,3 +142,2 @@ | ||
'should resend queued subscriptions': function (done) { | ||
this.timeout(4000) | ||
var connected = false | ||
@@ -142,0 +144,0 @@ |
var assert = require('assert') | ||
var StateMachine = require('../lib/state.js') | ||
var machine | ||
var Backoff = require('../lib/backoff.js') | ||
var sinon = require('sinon') | ||
var clock | ||
function maxBackoffStep (num) { | ||
if (num < Backoff.durations.length) { | ||
return Backoff.durations[num] + Backoff.maxSplay | ||
} else { | ||
return Backoff.fallback + Backoff.maxSplay | ||
} | ||
} | ||
exports['given a state machine'] = { | ||
beforeEach: function () { | ||
// create puts it in opened state. | ||
machine = StateMachine.create() | ||
machine._backoff.success() | ||
clock = sinon.useFakeTimers() | ||
@@ -37,5 +48,2 @@ }, | ||
'if the user calls disconnect the machine will reconnect after a delay': function (done) { | ||
this.timeout(4000) | ||
machine.open() | ||
machine.connect() | ||
@@ -48,8 +56,6 @@ assert.ok(machine.is('connecting')) | ||
machine.disconnect() | ||
clock.tick(2500) | ||
clock.tick(maxBackoffStep(0)) | ||
}, | ||
'the first connection should begin connecting, after disconnected it should automatically reconnect': function (done) { | ||
this.timeout(4000) | ||
machine.open() | ||
machine.connect() | ||
@@ -70,8 +76,6 @@ assert.ok(machine.is('connecting')) | ||
machine.disconnect() | ||
clock.tick(2500) | ||
clock.tick(maxBackoffStep(0)) | ||
}, | ||
'connections that hang should be detected after 10 seconds': function (done) { | ||
this.timeout(14000) | ||
'connections that hang should be detected after connect timeout': function (done) { | ||
machine.disconnect = function () { | ||
@@ -82,3 +86,3 @@ done() | ||
machine.connect() | ||
clock.tick(10001) | ||
clock.tick(machine._connectTimeout + 1) | ||
}, | ||
@@ -88,3 +92,2 @@ | ||
var once = true | ||
this.timeout(20000) | ||
var disconnects = 0 | ||
@@ -100,3 +103,3 @@ | ||
done() | ||
}, 15000) | ||
}, maxBackoffStep(0) + machine._connectTimeout) | ||
@@ -113,15 +116,26 @@ machine.on('connect', function () { | ||
clock.tick(15001) | ||
clock.tick(1 + maxBackoffStep(0) + machine._connectTimeout) | ||
}, | ||
'connections that fail should cause exponential backoff, finally emit unavailable': function (done) { | ||
this.timeout(65000) | ||
'connections that fail should cause exponential backoff, emit backoff times, finally emit unavailable': function (done) { | ||
var available = true | ||
var tries = 10 | ||
var tries = Backoff.durations.length + 1 | ||
var backoffs = [] | ||
machine.open() | ||
machine.on('backoff', function (time, failures) { | ||
backoffs.push(failures) | ||
var step = failures - 1 | ||
machine.on('unavailable', function () { | ||
assert(failures > 0) | ||
assert(time > 0) | ||
assert(time > (maxBackoffStep(step) - Backoff.maxSplay)) | ||
assert(time < (maxBackoffStep(step) + Backoff.maxSplay)) | ||
}) | ||
machine.once('unavailable', function () { | ||
available = false | ||
assert(backoffs.length > 1) | ||
assert(backoffs.length === machine._backoff.failures) | ||
assert(backoffs.length === Backoff.durations.length) | ||
done() | ||
@@ -138,7 +152,13 @@ }) | ||
clock.tick(64000) | ||
// Wait for all the backoffs + splay, then wait for fallback + splay as well | ||
var totalTimeToWait = 0 | ||
for (var i = 0; i < Backoff.durations.length; i++) { | ||
totalTimeToWait += maxBackoffStep(i) | ||
} | ||
totalTimeToWait += Backoff.fallback + Backoff.maxSplay | ||
clock.tick(1 + totalTimeToWait) | ||
}, | ||
'closing will cancel the guard timer': function () { | ||
machine.open() | ||
assert(!machine._guard) | ||
@@ -145,0 +165,0 @@ machine.connect() |
126012
3358