overleaf/services/document-updater/app/coffee/RateLimitManager.coffee

40 lines
1.4 KiB
CoffeeScript
Raw Normal View History

2017-05-26 07:10:57 -04:00
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)
2017-05-26 07:10:57 -04:00
_adjustLimitDown: () ->
@CurrentWorkerLimit = Math.max @BaseWorkerCount, (@CurrentWorkerLimit * 0.9)
logger.log {currentLimit: Math.ceil(@CurrentWorkerLimit)}, "reducing rate limit"
Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
2017-05-26 07:10:57 -04:00
_trackAndRun: (task, callback = () ->) ->
@ActiveWorkerCount++
Metrics.gauge "processingUpdates", @ActiveWorkerCount
2017-05-26 07:10:57 -04:00
task (err) =>
@ActiveWorkerCount--
Metrics.gauge "processingUpdates", @ActiveWorkerCount
2017-05-26 07:10:57 -04:00
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