From 5c25d15a182ffb0810f150bfe28e04fd6bf7af85 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Thu, 12 Jan 2017 09:25:18 +0000 Subject: [PATCH] WIP: try switch to rolling rate limiter --- .../coffee/infrastructure/RateLimiter.coffee | 36 ++++++++++--------- services/web/package.json | 3 +- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/services/web/app/coffee/infrastructure/RateLimiter.coffee b/services/web/app/coffee/infrastructure/RateLimiter.coffee index dd9c270794..7262890c4f 100644 --- a/services/web/app/coffee/infrastructure/RateLimiter.coffee +++ b/services/web/app/coffee/infrastructure/RateLimiter.coffee @@ -1,27 +1,29 @@ settings = require("settings-sharelatex") RedisWrapper = require('./RedisWrapper') rclient = RedisWrapper.client('ratelimiter') +RollingRateLimiter = require('rolling-rate-limiter') module.exports = RateLimiter = - _buildKey: (endpoint, subject) -> - return "RateLimiter:#{endpoint}:{#{subject}}" - addCount: (opts, callback = (err, shouldProcess)->)-> - k = RateLimiter._buildKey(opts.endpointName, opts.subjectName) - multi = rclient.multi() - multi.incr(k) - multi.get(k) - multi.expire(k, opts.timeInterval) - multi.exec (err, results)-> - count = results[1] - # account for the different results from `multi` when using cluster - if count instanceof Object - count = count[1] - allow = count < opts.throttle - callback err, allow + console.log ">> opts", opts + namespace = "RateLimit:#{opts.endpointName}:" + k = "{#{opts.subjectName}}" + limiter = RollingRateLimiter({ + redis: rclient, + namespace: namespace, + interval: opts.timeInterval * 1000, + maxInInterval: opts.throttle + }) + limiter k, (err, timeLeft, actionsLeft) -> + if err? + return callback(err) + allowed = timeLeft == 0 + console.log ">> limit", namespace, k, timeLeft, actionsLeft, ", allowed", allowed + callback(null, allowed) clearRateLimit: (endpointName, subject, callback) -> - k = RateLimiter._buildKey(endpointName, subject) - rclient.del k, callback + # same as the key which will be built by RollingRateLimiter (namespace+k) + keyName = "RateLimit:#{endpointName}:{#{subject}}" + rclient.del keyName, callback diff --git a/services/web/package.json b/services/web/package.json index 38ec9aebf2..27948d1645 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -63,7 +63,8 @@ "underscore": "1.6.0", "v8-profiler": "^5.2.3", "xml2js": "0.2.0", - "passport-saml": "^0.15.0" + "passport-saml": "^0.15.0", + "rolling-rate-limiter": "^0.1.4" }, "devDependencies": { "bunyan": "0.22.1",