Skip to content

Commit

Permalink
Add function execution rate limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
earldouglas committed Aug 30, 2015
1 parent d4830d5 commit e3e7171
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 7 deletions.
33 changes: 33 additions & 0 deletions src/teep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ module edc {
flatMap: <A,B>(xs: Array<A>, f: (A) => Array<B>): Array<B> => {
return array.flatten(array.map(xs, f));
},
filter: <A>(xs: Array<A>, f: (A) => boolean): Array<A> => {
return array.foldr(xs, [], (a: A, as: Array<A>): Array<A> => {
if (f(a)) {
as.push(a);
}
return as;
});
},
};

var object = {
Expand Down Expand Up @@ -104,6 +112,31 @@ module edc {
};
};
},
throttle: (limit: number, period: number, interval: number,
f: () => any): () => void => {
var times = [];
var throttled = function () {
var now = (new Date()).getTime();
times = array.filter(times, function (time) {
return now - time < period;
});
var withinLimit = times.length < limit
if (withinLimit) {
var newest = Math.max.apply(null, times);
var afterInterval = (now - newest) > interval;
if (afterInterval) {
times.push(now);
f();
} else {
setTimeout(throttled, interval - (now - newest));
}
} else {
var oldest = Math.min.apply(null, times);
setTimeout(throttled, period - (now - oldest));
}
};
return throttled;
}
};

export interface Monad<A> {
Expand Down
34 changes: 34 additions & 0 deletions teep.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ var edc;
},
flatMap: function (xs, f) {
return array.flatten(array.map(xs, f));
},
filter: function (xs, f) {
return array.foldr(xs, [], function (a, as) {
if (f(a)) {
as.push(a);
}
return as;
});
}
};
var object = {
Expand Down Expand Up @@ -95,6 +103,32 @@ var edc;
get: function () { return fMemo(x); }
};
};
},
throttle: function (limit, period, interval, f) {
var times = [];
var throttled = function () {
var now = (new Date()).getTime();
times = array.filter(times, function (time) {
return now - time < period;
});
var withinLimit = times.length < limit;
if (withinLimit) {
var newest = Math.max.apply(null, times);
var afterInterval = (now - newest) > interval;
if (afterInterval) {
times.push(now);
f();
}
else {
setTimeout(throttled, interval - (now - newest));
}
}
else {
var oldest = Math.min.apply(null, times);
setTimeout(throttled, period - (now - oldest));
}
};
return throttled;
}
};
var Some = (function () {
Expand Down
45 changes: 38 additions & 7 deletions test/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ describe('examples', function () {
var xs = teep.array.flatMap([1,3,5], alsoPlusOne);
assert.deepEqual([1,2,3,4,5,6], xs);
});
it('filter', function () {
var xs = teep.array.filter([1,2,3,4,5,6], function (x) {
return x % 2 === 1 || x === 4;
});
assert.deepEqual([1,3,4,5], xs);
});
});

describe('fn', function () {
Expand All @@ -51,9 +57,6 @@ describe('examples', function () {
assert.equal(nine, 9);
assert.equal(five, 5);
});
});

describe('fn', function () {
it('curry', function () {
function add(x, y) {
return x + y;
Expand All @@ -71,9 +74,6 @@ describe('examples', function () {
assert.equal(five, 5);
assert.equal(fortyTwo, 42);
});
});

describe('fn', function () {
it('memoize', function () {
function expensiveFn(n) {
for (var i = 0; i < 10000; i++) {
Expand All @@ -99,7 +99,6 @@ describe('examples', function () {
var fast = t3 - t2;
assert.ok(slow > 10 * fast); // over 10x faster
});

it('lazy', function () {
function expensiveFn(n) {
for (var i = 0; i < 10000; i++) {
Expand Down Expand Up @@ -129,6 +128,38 @@ describe('examples', function () {
var fast = t5 - t4;
assert.ok(slow > 10 * fast); // over 10x faster
});
it('rate', function (done) {
var xs = [];
var f = function () {
xs.push((new Date()).getTime());
};

var limit = 5;
var period = 50;
var interval = 5;
var count = 101;
var f2 = teep.fn.throttle(limit, period, interval, f);
for (var i = 0; i < count; i++) {
f2();
}

var check = function (above, below) {
if (xs.length <= above) {
done(Error(xs.length + ' should exceed ' + above));
} else if (xs.length > below) {
done(Error(xs.length + ' should not exceed ' + below));
} else if (xs.length < count) {
setTimeout(function () {
check(above + limit, below + limit);
}, period);
} else {
done();
}
};

setTimeout(function () { check(0, limit); }, period / 2);

});
});

describe('option', function () {
Expand Down

0 comments on commit e3e7171

Please sign in to comment.