@railzai/bottleneck
Version:
Distributed task scheduler and rate limiter
141 lines (114 loc) • 4.71 kB
text/coffeescript
parser = require "./parser"
BottleneckError = require "./BottleneckError"
class LocalDatastore
constructor: ( , , storeInstanceOptions) ->
= ._randomIndex()
parser.load storeInstanceOptions, storeInstanceOptions, @
= = = Date.now()
= 0
= 0
= 0
= .resolve()
= {}
_startHeartbeat: ->
if ! ? and ((
.reservoirRefreshInterval? and .reservoirRefreshAmount?
) or (
.reservoirIncreaseInterval? and .reservoirIncreaseAmount?
))
( = setInterval =>
now = Date.now()
if .reservoirRefreshInterval? and now >= + .reservoirRefreshInterval
= now
.reservoir = .reservoirRefreshAmount
._drainAll
if .reservoirIncreaseInterval? and now >= + .reservoirIncreaseInterval
{ reservoirIncreaseAmount: amount, reservoirIncreaseMaximum: maximum, reservoir } =
= now
incr = if maximum? then Math.min amount, maximum - reservoir else amount
if incr > 0
.reservoir += incr
._drainAll
, ).unref?()
else clearInterval
__publish__: (message) ->
await
.Events.trigger "message", message.toString()
__disconnect__: (flush) ->
await
clearInterval
.resolve()
yieldLoop: (t=0) -> new (resolve, reject) -> setTimeout resolve, t
computePenalty: -> .penalty ? ((15 * .minTime) or 5000)
__updateSettings__: (options) ->
await
parser.overwrite options, options,
._drainAll
true
__running__: ->
await
__queued__: ->
await
.queued()
__done__: ->
await
__groupCheck__: (time) ->
await
( + ) < time
computeCapacity: ->
{ maxConcurrent, reservoir } =
if maxConcurrent? and reservoir? then Math.min((maxConcurrent - ), reservoir)
else if maxConcurrent? then maxConcurrent -
else if reservoir? then reservoir
else null
conditionsCheck: (weight) ->
capacity =
not capacity? or weight <= capacity
__incrementReservoir__: (incr) ->
await
reservoir = .reservoir += incr
._drainAll
reservoir
__currentReservoir__: ->
await
.reservoir
isBlocked: (now) -> >= now
check: (weight, now) -> and ( - now) <= 0
__check__: (weight) ->
await
now = Date.now()
weight, now
__register__: (index, weight, expiration) ->
await
now = Date.now()
if weight
+= weight
if .reservoir? then .reservoir -= weight
wait = Math.max - now, 0
= now + wait + .minTime
{ success: true, wait, reservoir: .reservoir }
else { success: false }
strategyIsBlock: -> .strategy == 3
__submit__: (queueLength, weight) ->
await
if .maxConcurrent? and weight > .maxConcurrent
throw new BottleneckError("Impossible to add a job having a weight of #{weight} to a limiter having a maxConcurrent setting of #{@storeOptions.maxConcurrent}")
now = Date.now()
reachedHWM = .highWater? and queueLength == .highWater and not
blocked = and (reachedHWM or now)
if blocked
= now +
= + .minTime
._dropAllQueued()
{ reachedHWM, blocked, strategy: .strategy }
__free__: (index, weight) ->
await
-= weight
+= weight
._drainAll
{ running: }
module.exports = LocalDatastore