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
|
2017-05-30 09:36:51 -04:00
|
|
|
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"
|
2017-05-30 09:36:51 -04:00
|
|
|
Metrics.gauge "currentLimit", Math.ceil(@CurrentWorkerLimit)
|
2017-05-26 07:10:57 -04:00
|
|
|
|
|
|
|
_trackAndRun: (task, callback = () ->) ->
|
|
|
|
@ActiveWorkerCount++
|
2017-05-30 09:36:51 -04:00
|
|
|
Metrics.gauge "processingUpdates", @ActiveWorkerCount
|
2017-05-26 07:10:57 -04:00
|
|
|
task (err) =>
|
|
|
|
@ActiveWorkerCount--
|
2017-05-30 09:36:51 -04:00
|
|
|
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"
|
2017-06-07 06:47:28 -04:00
|
|
|
@_trackAndRun task, (err) =>
|
|
|
|
@_adjustLimitUp() if !err? # don't increment rate limit if there was an error
|
|
|
|
callback(err) # only return after task completes
|