RateLimiter.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. const settings = require('settings-sharelatex')
  2. const Metrics = require('metrics-sharelatex')
  3. const RedisWrapper = require('./RedisWrapper')
  4. const rclient = RedisWrapper.client('ratelimiter')
  5. const RollingRateLimiter = require('rolling-rate-limiter')
  6. const { promisifyAll } = require('../util/promises')
  7. const RateLimiter = {
  8. addCount(opts, callback) {
  9. if (settings.disableRateLimits) {
  10. return callback(null, true)
  11. }
  12. if (callback == null) {
  13. callback = function() {}
  14. }
  15. const namespace = `RateLimit:${opts.endpointName}:`
  16. const k = `{${opts.subjectName}}`
  17. const limiter = RollingRateLimiter({
  18. redis: rclient,
  19. namespace,
  20. interval: opts.timeInterval * 1000,
  21. maxInInterval: opts.throttle
  22. })
  23. limiter(k, function(err, timeLeft, actionsLeft) {
  24. if (err) {
  25. return callback(err)
  26. }
  27. const allowed = timeLeft === 0
  28. if (!allowed) {
  29. Metrics.inc('rate-limit-hit', 1, {
  30. path: opts.endpointName
  31. })
  32. }
  33. return callback(null, allowed)
  34. })
  35. },
  36. clearRateLimit(endpointName, subject, callback) {
  37. // same as the key which will be built by RollingRateLimiter (namespace+k)
  38. const keyName = `RateLimit:${endpointName}:{${subject}}`
  39. rclient.del(keyName, callback)
  40. }
  41. }
  42. RateLimiter.promises = promisifyAll(RateLimiter)
  43. module.exports = RateLimiter