Skip to content

calling a Redis function(loaded Lua script) using Lettuce library

I am using Java, Spring-Boot, Redis 7.0.4, and lettuce 6.2.0.RELEASE.

I wrote a Lua script as below:

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 ='HGET', jobsKey ,jobRef)
  local jobObj = cmsgpack.unpack(jobDetail)
  local msgSteps = jobObj['steps']
  msgSteps[jobIdentity] = 'IN_PROGRESS'
  jobDetail ='HSET', jobsKey, jobRef, cmsgpack.pack(jobObj))
  local ssoMsg ='RPUSH', inboxKey, cmsgpack.pack(accountsMsg))

  return jobDetail
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!!



After a bit more research about the requirement, I found the following StackOverFlow answer:

StackOverFlow Answer

And also based on the documentation:

Redis Custom Commands :

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(
                    (message.getAgent() + Constant.AGENTS_JOBS_POSTFIX).getBytes(StandardCharsets.UTF_8),
                    (message.getAgent() + Constant.AGENTS_INBOX_POSTFIX).getBytes(StandardCharsets.UTF_8),
        } catch (Exception e) {