Просмотр исходного кода

WIP: try switch to rolling rate limiter

Shane Kilkelly 9 лет назад
Родитель
Сommit
5c25d15a18
2 измененных файлов с 21 добавлено и 18 удалено
  1. 19 17
      services/web/app/coffee/infrastructure/RateLimiter.coffee
  2. 2 1
      services/web/package.json

+ 19 - 17
services/web/app/coffee/infrastructure/RateLimiter.coffee

@@ -1,27 +1,29 @@
 settings = require("settings-sharelatex")
 settings = require("settings-sharelatex")
 RedisWrapper = require('./RedisWrapper')
 RedisWrapper = require('./RedisWrapper')
 rclient = RedisWrapper.client('ratelimiter')
 rclient = RedisWrapper.client('ratelimiter')
+RollingRateLimiter = require('rolling-rate-limiter')
 
 
 
 
 module.exports = RateLimiter =
 module.exports = RateLimiter =
 
 
-	_buildKey: (endpoint, subject) ->
-		return "RateLimiter:#{endpoint}:{#{subject}}"
-
 	addCount: (opts, callback = (err, shouldProcess)->)->
 	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) ->
 	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

+ 2 - 1
services/web/package.json

@@ -63,7 +63,8 @@
     "underscore": "1.6.0",
     "underscore": "1.6.0",
     "v8-profiler": "^5.2.3",
     "v8-profiler": "^5.2.3",
     "xml2js": "0.2.0",
     "xml2js": "0.2.0",
-    "passport-saml": "^0.15.0"
+    "passport-saml": "^0.15.0",
+    "rolling-rate-limiter": "^0.1.4"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "bunyan": "0.22.1",
     "bunyan": "0.22.1",