overleaf/services/document-updater/app/coffee/RateLimitManager.coffee
2017-06-07 11:47:28 +01:00

39 lines
1.4 KiB
CoffeeScript

Settings = require('settings-sharelatex')
logger = require('logger-sharelatex')
Metrics = require('./Metrics')
module.exports = class RateLimiter
constructor: (number = 10) ->
@ActiveWorkerCount = 0
@CurrentWorkerLimit = number
@BaseWorkerCount = number
_adjustLimitUp: () ->
@CurrentWorkerLimit += 0.1 # allow target worker limit to increase gradually
Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
_adjustLimitDown: () ->
@CurrentWorkerLimit = Math.max @BaseWorkerCount, (@CurrentWorkerLimit * 0.9)
logger.log {currentLimit: Math.ceil(@CurrentWorkerLimit)}, "reducing rate limit"
Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
_trackAndRun: (task, callback = () ->) ->
@ActiveWorkerCount++
Metrics.gauge "processingUpdates", @ActiveWorkerCount
task (err) =>
@ActiveWorkerCount--
Metrics.gauge "processingUpdates", @ActiveWorkerCount
callback(err)
run: (task, callback) ->
if @ActiveWorkerCount < @CurrentWorkerLimit
@_trackAndRun task # below the limit, just put the task in the background
callback() # return immediately
if @CurrentWorkerLimit > @BaseWorkerCount
@_adjustLimitDown()
else
logger.log {active: @ActiveWorkerCount, currentLimit: Math.ceil(@CurrentWorkerLimit)}, "hit rate limit"
@_trackAndRun task, (err) =>
@_adjustLimitUp() if !err? # don't increment rate limit if there was an error
callback(err) # only return after task completes