Skip to content

Commit

Permalink
TimeSyncing using a stats library + slow server faking
Browse files Browse the repository at this point in the history
  • Loading branch information
tonistiigi committed Mar 26, 2012
1 parent 62e18ee commit 57e8e87
Show file tree
Hide file tree
Showing 5 changed files with 540 additions and 21 deletions.
20 changes: 20 additions & 0 deletions lib/backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ var argv = optimist.options('port', {
alias: 'l',
"default": 'info',
describe: 'Log level'
}).options('slow', {
bool: true,
describe: 'Fake slow connection'
}).argv;

winston.setLevels(winston.config.syslog.levels);
Expand Down Expand Up @@ -60,6 +63,23 @@ app.get('/', function(req, res, next){
function getTime(cb){
return cb(new Date().getTime());
}
function makeSlow(func) {
return function(cb){
setTimeout(function(){
func(function(){
var args = arguments;
setTimeout(function(){
cb.apply(null, args);
}, 200 + (Math.random()*20) + (Math.random()>.90?100:0) + (Math.random()>.97?300:0));
});
}, 200 + (Math.random()*20)+ (Math.random()>.90?100:0) + (Math.random()>.97?300:0));
};
}

if(argv.slow){
winston.notice('Server running on slow mode');
getTime = makeSlow(getTime);
}

var channels = {};

Expand Down
1 change: 1 addition & 0 deletions lib/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ <h1 id="title"></h1>

<!-- scripts concatenated and minified via ant build script-->
<script src="/js/helper.js"></script>
<script src="/js/faststats.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/js/libs/underscore.js"></script>
<script src="/js/libs/backbone.js"></script>
Expand Down
57 changes: 36 additions & 21 deletions lib/public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,12 @@ ms.bind('progress', function() {
});
*/



if(typeof ms == "undefined") {
ms = {};
}

_.avg = function (values) {
return _.reduce(values, function(a, b){ return a + b; }, 0) / values.length;
};

var pathparts = window.location.pathname.split('/');
ms.channel = pathparts[1];

Expand All @@ -75,25 +67,27 @@ _.extend(ms, Backbone.Events);
// Measure helper class
var Measure = function(opt) {
this.opt = _.defaults(opt || {}, {
samples: 3,
retries: 3,
minSamples: 4,
maxSamples: 30,
maxErrors: 5,
timeout: 400,
sleep: 120, //ms
deviation: 30,
sleep: 50, //ms
moe: 10,
max: null,
min: null
});
this.errors = 0;
this.ready = false;
this.value = 0;
this.i = 0;
this.samples = 0;

_.bindAll(this, 'measure');
};
Measure.prototype = _.extend(Backbone.Events, {
run: function(iterator) {
this.iterator = iterator;
this.results = [];
this.results = new Stats();
this.measure();
},
measure: function() {
Expand All @@ -103,14 +97,14 @@ Measure.prototype = _.extend(Backbone.Events, {
},
measureResponder: function(index, result){
if (this.i != index) {
return this.trigger('error', {msg: 'Wrong response order.'});
return;
//return this.trigger('error', {msg: 'Wrong response order.'});
}
var timeNow = new Date().getTime();
if ((this.opt.timeout == null && timeNow - this._requestTime > this.opt.timeout) ||
(this.results.length && Math.abs(_.avg(this.results) - result) > this.opt.deviation) ||
(this.opt.min != null && result < this.opt.min) || (this.opt.max != null && result > this.opt.max)) {
this.errors++;
if (this.errors >= this.opt.retries) {
if (this.errors >= this.opt.maxErrors) {
this.ready = false;
this.trigger('error', {msg: 'Max retries limit'});
}
Expand All @@ -119,15 +113,36 @@ Measure.prototype = _.extend(Backbone.Events, {
}
}
else {
this.samples++;
this.results.push(result);
if (this.results.length >= this.opt.samples) {
this.value = _.avg(this.results);
if (this.samples < this.opt.minSamples) {
return _.delay(this.measure, this.opt.sleep);
}

var moe = this.results.moe();
var moeReq = this.opt.moe;
if (this.samples < this.opt.maxSamples * .3) {
moeReq*=.5;
}
else if(this.samples > this.opt.maxSamples * .85){
moeReq*=2;
}
if (moe <= moeReq) {
this.ready = true;
this.trigger('ready', this.value);
this.value = this.results.amean();
return this.trigger('ready', this.value);
}
else {
_.delay(this.measure, this.opt.sleep);
//console.log('result was', result, this.results.amean(), moe, moeReq, this.samples);
if (this.samples >= this.opt.maxSamples) {
this.ready = false;
return this.trigger('error', {msg: 'Max samples limit'});
}

if (this.samples >= this.minSamples) {
this.results = this.results.irq();
}

_.delay(this.measure, this.opt.sleep);
}

}
Expand Down
Loading

0 comments on commit 57e8e87

Please sign in to comment.