Class: Berater::ConcurrencyLimiter

Inherits:
Limiter
  • Object
show all
Defined in:
lib/berater/concurrency_limiter.rb

Constant Summary collapse

LUA_SCRIPT =
Berater::LuaScript(<<~LUA
  local key = KEYS[1]
  local lock_key = KEYS[2]
  local capacity = tonumber(ARGV[1])
  local ts = tonumber(ARGV[2])
  local ttl = tonumber(ARGV[3])
  local cost = tonumber(ARGV[4])
  local lock_ids = {}

  -- purge stale hosts
  if ttl > 0 then
    redis.call('ZREMRANGEBYSCORE', key, 0, ts - ttl)
  end

  -- check capacity
  local count = redis.call('ZCARD', key)

  if cost == 0 then
    -- just checking count
    table.insert(lock_ids, true)
  elseif (count + cost) <= capacity then
    -- grab locks, one per cost
    local lock_id = redis.call('INCRBY', lock_key, cost)
    local locks = {}

    for i = lock_id - cost + 1, lock_id do
      table.insert(lock_ids, i)

      table.insert(locks, ts)
      table.insert(locks, i)
    end

    redis.call('ZADD', key, unpack(locks))
    count = count + cost

    if ttl > 0 then
      redis.call('PEXPIRE', key, ttl)
    end
  end

  return { count, unpack(lock_ids) }
LUA
)

Instance Attribute Summary

Attributes inherited from Limiter

#capacity, #key, #options

Instance Method Summary collapse

Methods inherited from Limiter

#==, #limit, new, #redis, #utilization

Constructor Details

#initialize(key, capacity, **opts) ⇒ ConcurrencyLimiter

Returns a new instance of ConcurrencyLimiter.



4
5
6
7
8
9
10
11
# File 'lib/berater/concurrency_limiter.rb', line 4

def initialize(key, capacity, **opts)
  super(key, capacity, **opts)

  # truncate fractional capacity
  self.capacity = capacity.to_i

  self.timeout = opts[:timeout] || 0
end

Instance Method Details

#timeoutObject



13
14
15
# File 'lib/berater/concurrency_limiter.rb', line 13

def timeout
  options[:timeout]
end

#to_sObject



89
90
91
# File 'lib/berater/concurrency_limiter.rb', line 89

def to_s
  "#<#{self.class}(#{key}: #{capacity} at a time)>"
end