Module: Ihasa::Lua

Defined in:
lib/ihasa/lua.rb

Overview

Contains lua related logic

Constant Summary collapse

NOW_DECLARATION =
<<-LUA.freeze
  redis.replicate_commands()
  local now = redis.call('TIME')
  now = now[1] + now[2] * 10 ^ -6
LUA
ALLOWANCE_UPDATE_STATEMENT =
<<-LUA.freeze
  allowance = allowance + (elapsed * rate)
  if allowance > burst then
    allowance = burst
  end
LUA
ELAPSED_STATEMENT =
'local elapsed = now - last'.freeze
SEP =
"\n".freeze
LOCAL_VARIABLES =
Ihasa::OPTIONS
.map { |key| to_local(key) }
.tap { |vars| vars << ELAPSED_STATEMENT }.join(SEP).freeze
TOKEN_BUCKET_ALGORITHM_BODY =
<<-LUA.freeze
  #{LOCAL_VARIABLES}
  #{ALLOWANCE_UPDATE_STATEMENT}
  local result = #{Ihasa::NOK}
  if allowance >= 1.0 then
    allowance = allowance - 1.0
    result = #{Ihasa::OK}
  end
  #{set(last, 'now')}
  #{set(allowance, 'allowance')}
  return result
LUA
TOKEN_BUCKET_ALGORITHM =
<<-LUA.freeze
  #{NOW_DECLARATION}
  #{TOKEN_BUCKET_ALGORITHM_BODY}
LUA
TOKEN_BUCKET_HASH =
Digest::SHA1.hexdigest(
  Lua::TOKEN_BUCKET_ALGORITHM
).freeze

Class Method Summary collapse

Class Method Details

.configuration(rate_value, burst_value, now_declaration = NOW_DECLARATION) ⇒ Object

Please note that the replicate_commands is mandatory when using a non deterministic command before writing shit to the redis instance for versions >= 3.2



26
27
28
29
30
31
32
33
34
# File 'lib/ihasa/lua.rb', line 26

def configuration(rate_value, burst_value, now_declaration = NOW_DECLARATION)
  <<-LUA
    #{now_declaration}
    #{set rate, rate_value}
    #{set burst, burst_value}
    #{set allowance, burst_value}
    #{set last, 'now'}
  LUA
end

.exists?(key) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/ihasa/lua.rb', line 52

def exists?(key)
  "redis.call('EXISTS', #{key})"
end

.fetch(key) ⇒ Object



40
41
42
# File 'lib/ihasa/lua.rb', line 40

def fetch(key)
  "KEYS[#{index key}]"
end

.get(key) ⇒ Object



44
45
46
# File 'lib/ihasa/lua.rb', line 44

def get(key)
  "tonumber(redis.call('GET', #{key}))"
end

.index(key) ⇒ Object



36
37
38
# File 'lib/ihasa/lua.rb', line 36

def index(key)
  Integer(Ihasa::OPTIONS.index(key)) + 1
end

.method_missing(sym, *args, &block) ⇒ Object



56
57
58
59
# File 'lib/ihasa/lua.rb', line 56

def method_missing(sym, *args, &block)
  super unless Ihasa::OPTIONS.include? sym
  fetch sym
end

.now_declaration(value) ⇒ Object



19
20
21
# File 'lib/ihasa/lua.rb', line 19

def now_declaration(value)
  "local now = #{value}"
end

.set(key, value) ⇒ Object



48
49
50
# File 'lib/ihasa/lua.rb', line 48

def set(key, value)
  "redis.call('SET', #{key}, tostring(#{value}))"
end

.to_local(key) ⇒ Object



61
62
63
# File 'lib/ihasa/lua.rb', line 61

def to_local(key)
  "local #{key} = tonumber(#{get(fetch(key))})"
end

.token_bucket_algorithm_legacy(now_value) ⇒ Object



65
66
67
68
69
70
# File 'lib/ihasa/lua.rb', line 65

def token_bucket_algorithm_legacy(now_value)
  <<-LUA.freeze
    #{now_declaration(now_value)}
    #{TOKEN_BUCKET_ALGORITHM_BODY}
  LUA
end