Allow executing scripts inside queueing mode
Hey guys!
Right now it's not allowed to execute Lua scripts from MULTI block, due to check in the JedisScriptingCommands.
As far as I know, this behavior is allowed by Redis
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> eval "return 42" 0
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 42
and WATCH is also working correctly in such circumstances
127.0.0.1:6379> incr test
(integer) 2
127.0.0.1:6379> watch test
OK
127.0.0.1:6379> multi
OK
# MODIFYING test value from a different client here
127.0.0.1:6379> eval "return 42" 0
QUEUED
127.0.0.1:6379> exec
(nil)
To give you some context we have a use case when we have a
- user_data
- counter
The
user_datathat needs to be checked inside app logic (cannot move it to lua :( ), modified and committed together with the counter update
We want to process this in the following manner (pseudo code here):
WATCHuser_dataGETuser_data- Do some application-level checks and magic
- Start
MULTI - Execute a script that will decrement the counter and update user_data
- Run
EXEC
Unfortunately, this is failing right now with
2021-03-03 12:19:28.877 ERROR 36671 --- [ Test worker] c.d.magpie.service.AssignShiftAction : java.lang.UnsupportedOperationException
at org.springframework.data.redis.connection.jedis.JedisScriptingCommands.eval(JedisScriptingCommands.java:124)
at org.springframework.data.redis.connection.DefaultedRedisConnection.eval(DefaultedRedisConnection.java:1523)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:61)
Is this intended behavior or this check can be removed?
Thanks for bringing up the issue. For quite a while, Jedis' Pipeline and its super-type MultiKeyCommandsPipeline didn't define eval nor script… methods. Seems we missed that Jedis caught up for eval and evalsha. Are you interested in providing a pull request that enables scripting commands for eval and evalSha methods?
Hey @mp911de , thanks for the quick answer!
As far I understood, the idea is to just remove connection.isQueueing() from JedisScriptingCommands class, right? Or addition refactor is needed?
And btw, connection.isPipelined()is also excessive in this context in this case
We need to apply two changes:
- Remove the guards that avoid calling the Jedis methods
- Update the call to JedisInvoker to call
eval/evalshaon theMultiKeyCommandsPipelineobject.
Likely, a few tests rely on when they run in pipelining/transaction mode an exception is thrown.