I am using Java
, Spring-Boot
, Redis 7.0.4
, and lettuce 6.2.0.RELEASE
.
I wrote a Lua
script as below:
#!lua name = updateRegisterUserJobAndForwardMsg function updateRegisterUserJobAndForwardMsg (KEYS, ARGV) local jobsKey = KEYS[1] local inboxKey = KEYS[2] local jobRef = KEYS[3] local jobIdentity = KEYS[4] local accountsMsg = ARGV[1] local jobDetail = redis.call('HGET', jobsKey ,jobRef) local jobObj = cmsgpack.unpack(jobDetail) local msgSteps = jobObj['steps'] msgSteps[jobIdentity] = 'IN_PROGRESS' jobDetail = redis.call('HSET', jobsKey, jobRef, cmsgpack.pack(jobObj)) local ssoMsg = redis.call('RPUSH', inboxKey, cmsgpack.pack(accountsMsg)) return jobDetail end redis.register_function('updateRegisterUserJobAndForwardMsg', updateRegisterUserJobAndForwardMsg)
Then I registered it as a function in my Redis
using the below command:
cat updateJobAndForwardMsgScript.lua | redis-cli -x FUNCTION LOAD REPLACE
Now I can easily call my function using Redis-cli
as below:
FCALL updateJobAndForwardMsg 4 key1 key2 key3 key4 arg1
And it will get executed successfully!!
Now I want to call my function using lettuce
which is my Redis-client
library in my application, but I haven’t found anything on the net, and it seems that lettuce
does not support Redis 7 new feature
for calling FUNCTION
using FCALL
command!!
Does it have any other customized way for executing Redis commands using lettuce?
Any help would be appreciated!!
Advertisement
Answer
After a bit more research about the requirement, I found the following StackOverFlow answer:
And also based on the documentation:
Custom commands can be dispatched on the one hand using Lua and the eval() command, on the other side Lettuce 4.x allows you to trigger own commands. That API is used by Lettuce itself to dispatch commands and requires some knowledge of how commands are constructed and dispatched within Lettuce.
Lettuce provides two levels of command dispatching:
Using the synchronous, asynchronous or reactive API wrappers which invoke commands according to their nature
Using the bare connection to influence the command nature and synchronization (advanced)
So I could handle my requirements by creating an interface
which extends
the io.lettuce.core.dynamic.Commands
interface
as below:
public interface CustomCommands extends Commands { @Command("FCALL :funcName :keyCnt :jobsKey :inboxRef :jobsRef :jobIdentity :frwrdMsg ") Object fcall_responseJob(@Param("funcName") byte[] functionName, @Param("keyCnt") Integer keysCount, @Param("jobsKey") byte[] jobsKey, @Param("inboxRef") byte[] inboxRef, @Param("jobsRef") byte[] jobsRef, @Param("jobIdentity") byte[] jobIdentity, @Param("frwrdMsg") byte[] frwrdMsg); }
Then I could easily call my loaded FUNCTION
(which was a Lua script) as below:
private void updateResponseJobAndForwardMsgToSSO(SharedObject message, SharedObject responseMessage) { try { ObjectMapper objectMapper = new MessagePackMapper(); RedisCommandFactory factory = new RedisCommandFactory(connection); CustomCommands commands = factory.getCommands(CustomCommands.class); Object obj = commands.fcall_responseJob( Constant.REDIS_RESPONSE_JOB_FUNCTION_NAME.getBytes(StandardCharsets.UTF_8), Constant.REDIS_RESPONSE_JOB_FUNCTION_KEY_COUNT, (message.getAgent() + Constant.AGENTS_JOBS_POSTFIX).getBytes(StandardCharsets.UTF_8), (message.getAgent() + Constant.AGENTS_INBOX_POSTFIX).getBytes(StandardCharsets.UTF_8), message.getReferenceNumber().getBytes(StandardCharsets.UTF_8), message.getTyp().getBytes(StandardCharsets.UTF_8), objectMapper.writeValueAsBytes(responseMessage)); LOG.info(obj.toString()); } catch (Exception e) { e.printStackTrace(); } }