RateLimitManager.coffee 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. Settings = require('settings-sharelatex')
  2. logger = require('logger-sharelatex')
  3. Metrics = require('./Metrics')
  4. module.exports = class RateLimiter
  5. constructor: (number = 10) ->
  6. @ActiveWorkerCount = 0
  7. @CurrentWorkerLimit = number
  8. @BaseWorkerCount = number
  9. _adjustLimitUp: () ->
  10. @CurrentWorkerLimit += 0.1 # allow target worker limit to increase gradually
  11. Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
  12. _adjustLimitDown: () ->
  13. @CurrentWorkerLimit = Math.max @BaseWorkerCount, (@CurrentWorkerLimit * 0.9)
  14. logger.log {currentLimit: Math.ceil(@CurrentWorkerLimit)}, "reducing rate limit"
  15. Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
  16. _trackAndRun: (task, callback = () ->) ->
  17. @ActiveWorkerCount++
  18. Metrics.gauge "processingUpdates", @ActiveWorkerCount
  19. task (err) =>
  20. @ActiveWorkerCount--
  21. Metrics.gauge "processingUpdates", @ActiveWorkerCount
  22. callback(err)
  23. run: (task, callback) ->
  24. if @ActiveWorkerCount < @CurrentWorkerLimit
  25. @_trackAndRun task # below the limit, just put the task in the background
  26. callback() # return immediately
  27. if @CurrentWorkerLimit > @BaseWorkerCount
  28. @_adjustLimitDown()
  29. else
  30. logger.log {active: @ActiveWorkerCount, currentLimit: Math.ceil(@CurrentWorkerLimit)}, "hit rate limit"
  31. @_trackAndRun task, (err) =>
  32. @_adjustLimitUp() if !err? # don't increment rate limit if there was an error
  33. callback(err) # only return after task completes