Created
December 22, 2023 10:54
-
-
Save macgena/caeff5eebe13e241757f7a695ac43602 to your computer and use it in GitHub Desktop.
Redis Counter With Limit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- This script increments a counter and returns a boolean indicating whether the counter is below a limit. -- | |
-- If the counter is below the limit, the counter is incremented and the new value is returned. -- | |
-- If the counter is above the limit, the counter is not incremented and the current value is returned. -- | |
-- The counter is set to expire after 60 seconds. -- | |
-- ARGV[1] - The key of the counter in Redis -- | |
-- ARGV[2] - The command INCR or DECR -- | |
-- ARGV[3] - Limit to check against -- | |
local counter | |
local counter_key = ARGV[1] | |
local command = ARGV[2] | |
local limit = tonumber(ARGV[3]) | |
local expiration_in_seconds = 60 | |
local success = false | |
counter = redis.call("GET", counter_key) | |
if counter == false then | |
counter = 0 | |
end | |
if tonumber(counter) < limit and command == "INCR" then | |
success = true | |
counter = redis.call("INCR", counter_key) | |
elseif tonumber(counter) > limit and command == "DECR" then | |
success = true | |
counter = redis.call("DECR", counter_key) | |
end | |
redis.call("EXPIRE", counter_key, expiration_in_seconds) | |
return { success, tonumber(counter) } | |
-- Example of call -- | |
-- EVAL ${LUA_SCRIPT_ABOVE_AS_STRING} 0 test_key INCR 10 -- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
module RedisHelpers | |
module CounterWithLimit | |
LUA_SCRIPT = File.read("#{__dir__}/counter_with_limit.lua").freeze | |
# NOTE: Redis returns 1 for true and nil for false when LUA script is executed | |
SUCCESS_VALUE = 1 | |
module_function | |
def try_incr(key:, limit:, redis: Redis.new) | |
# NOTE: https://redis.io/commands/eval/ | |
success, counter = redis.call('EVAL', LUA_SCRIPT, 0, key, 'INCR', limit) | |
{ success: success == SUCCESS_VALUE, counter: } | |
end | |
def try_decr(key:, limit: 0, redis: Redis.new) | |
# NOTE: https://redis.io/commands/eval/ | |
success, counter = redis.call('EVAL', LUA_SCRIPT, 0, key, 'DECR', limit) | |
{ success: success == SUCCESS_VALUE, counter: } | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment