-
-
Save antirez/950965 to your computer and use it in GitHub Desktop.
# Conditional decrement. | |
# | |
# Decrement the value of a key only if the current value is greater than | |
# a specified value. | |
require 'rubygems' | |
require 'redis' | |
r = Redis.new | |
cond_decr = <<LUA | |
local value = tonumber(redis('get',KEYS[1])) | |
if value == nil then return {err="Value at key is not integer"} end | |
if value > tonumber(ARGV[1]) | |
then | |
value = value - 1 | |
redis('set',KEYS[1],value) | |
end | |
return value | |
LUA | |
r.set(:x,4) | |
5.times { | |
puts(r.eval(cond_decr,1,:x,0)) | |
} |
Why don't you declare global functions "set" and "get" instead of putting everything in a "redis" function? It would improve error message consistency: you wouldn't have to create a special error message to tell the user the command is unknown, he would get an "attempt to call nil" kind of error.
@antirez: Yeah, but:
- That means that errors don't evaluate to false in an if statement.
- It's very unlike normal Lua behavior, which would probably confuse people who already know Lua.
I still think that representing Redis errors with Lua errors would be the best solution. 90% of the time, errors in Redis represent exceptional conditions like improperly calling a command, which is exactly what Lua errors are used for. If there was a time where not directly erroring to the user was important, you could local ok, result = pcall(redis, "get", somekey)
. ok
would contain true or false depending on whether it worked or not, and result
would contain either the result of the operation or the error message.
The {ok = "OK"}
is a pretty good idea though.
@doub: Because then he would have to define a C-level function for every single Redis command, not to mention polluting the global namespace to heck.
@leafstorm: If you have a single function, you have to do the dispatch inside the called C function anyway. If there are that many commands to bind, use a code generator. And to avoid polluting global namespace you can put it in a (preloaded) module.
@doub People could do something like https://gist.github.com/952677 if they need it. It might be better to leave such things to third party lua libs and keep the redis code simple.
Hey, thanks for the suggestions. @leafstorm: the translation happens exactly as you described it but for errors.
My point for using {err = ...} is that I want all the errors be single return values for a matter of unification, since in lua you can do something like:
return redis("get",...)
And everything happens in the real command is returned by Redis, BUT for status code reply, for which I should probably use {ok=...}.
Similarly you should be able to call a Redis command without even caring about what he returned, save the reply into a var, and return it later as the user directly called Redis:
reply = redis(".....");
... do more stuff ....
return reply
I think this is much more important compared to Lua idiomatic error handling since what hides inside the above concept is that Redis errors are a data type and not a condition.
Btw nothing is written in the stone as this is an "idea evaluation" branch and we can change everything in the future.