Class: GCRA::RedisStore
- Inherits:
-
Object
- Object
- GCRA::RedisStore
- Defined in:
- lib/gcra/redis_store.rb
Overview
Redis store, expects all timestamps and durations to be integers with nanoseconds since epoch.
Constant Summary collapse
- CAS_SCRIPT =
"local v = redis.call('get', KEYS[1])\nif v == false then\n return redis.error_reply(\"key does not exist\")\nend\nif v ~= ARGV[1] then\n return 0\nend\nredis.call('psetex', KEYS[1], ARGV[3], ARGV[2])\nreturn 1\n".freeze
- CAS_SCRIPT_MISSING_KEY_RESPONSE =
'key does not exist'.freeze
Instance Method Summary collapse
-
#compare_and_set_with_ttl(key, old_value, new_value, ttl_nano) ⇒ Object
Atomically compare the value at key to the old value.
-
#get_with_time(key) ⇒ Object
Returns the value of the key or nil, if it isn’t in the store.
-
#initialize(redis, key_prefix) ⇒ RedisStore
constructor
A new instance of RedisStore.
-
#set_if_not_exists_with_ttl(key, value, ttl_nano) ⇒ Object
Set the value of key only if it is not already set.
Constructor Details
#initialize(redis, key_prefix) ⇒ RedisStore
17 18 19 20 |
# File 'lib/gcra/redis_store.rb', line 17 def initialize(redis, key_prefix) @redis = redis @key_prefix = key_prefix end |
Instance Method Details
#compare_and_set_with_ttl(key, old_value, new_value, ttl_nano) ⇒ Object
Atomically compare the value at key to the old value. If it matches, set it to the new value and return true. Otherwise, return false. If the key does not exist in the store, return false with no error. If the swap succeeds, update the ttl for the key atomically.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/gcra/redis_store.rb', line 53 def compare_and_set_with_ttl(key, old_value, new_value, ttl_nano) full_key = @key_prefix + key begin ttl_milli = calculate_ttl_milli(ttl_nano) swapped = @redis.eval(CAS_SCRIPT, keys: [full_key], argv: [old_value, new_value, ttl_milli]) rescue Redis::CommandError => e if e. == CAS_SCRIPT_MISSING_KEY_RESPONSE return false end raise end return swapped == 1 end |
#get_with_time(key) ⇒ Object
Returns the value of the key or nil, if it isn’t in the store. Also returns the time from the Redis server, with microsecond precision.
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/gcra/redis_store.rb', line 24 def get_with_time(key) time_response = @redis.time # returns tuple (seconds since epoch, microseconds) # Convert tuple to nanoseconds time = (time_response[0] * 1_000_000 + time_response[1]) * 1_000 value = @redis.get(@key_prefix + key) if value != nil value = value.to_i end return value, time end |
#set_if_not_exists_with_ttl(key, value, ttl_nano) ⇒ Object
Set the value of key only if it is not already set. Return whether the value was set. Also set the key’s expiration (ttl, in seconds). The operations are not performed atomically.
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/gcra/redis_store.rb', line 38 def set_if_not_exists_with_ttl(key, value, ttl_nano) full_key = @key_prefix + key did_set = @redis.setnx(full_key, value) if did_set ttl_milli = calculate_ttl_milli(ttl_nano) @redis.pexpire(full_key, ttl_milli) end return did_set end |