miniredis icon indicating copy to clipboard operation
miniredis copied to clipboard

Lua call redis.call('SET', ...) returns string type in miniredis but table type in real Redis

Open mpetronic opened this issue 3 years ago • 2 comments

The response from certain Redis calls in my Lua script does not conform to those from real Redis instance. This means I cannot test my code that uses Lua scripts correctly when the same Lua script is used in unit tests (miniredis) and integration tests (real Redis).

For example, this code behaves differently in my unit tests (using miniredis) and my integration test (using a docker instance of redis:6.2.5-buster):

# The issue is here where miniredis returns a string but real redis return a table
local result = redis.call('SET', lockKey, lockId, 'NX')

# Real Redis returns the result as a table. If the outcome is successful, then the table
# has one entry with key='ok' and value=' OK' (result['ok'] = 'OK'). If the  outcome is 
# an error, then the table has one entry with key='err' and value='the error msg'.
# NOTE: From what I have read, I am fairly sure the value for the 'err' is the error message
# but have not proven that, I have proven the 'ok' part which was enough to identify this
# as an issue.

# So, this works in real Redis but fails in miniredis because result['ok'] on the 
# string-based miniredis response evaluates to a nil.

if result['ok] == 'OK' then
   do other stuff
else
  return result
end

# For it to work in miniredis, you have to do this, expecting a string instead of a table:

if result == 'OK' then
   do other stuff
else
  return result
end

I suppose I could work around this by testing the type so that one common Lua script can be used that works with both miniredis and real Redis but it would be nice if miniredis mirrored the real Redis in this case.

Nevertheless, miniredis is a great tool and thank you for creating it for the community!

mpetronic avatar Feb 19 '22 17:02 mpetronic

Hi Mark, thanks for your report! Interesting that no-one ran into this yet.

It looks like redis.call() cares if the result is a "simple string" or a "bulk string". If it is a simple string it makes the table with the "ok" field. Miniredis did not do that at all. There is a fix in the linked PR, but I'm not really happy with the solution, so I'll think about it a bit more.

alicebob avatar Feb 21 '22 08:02 alicebob

merged in master, will make it a release later.

alicebob avatar Feb 23 '22 08:02 alicebob