package org.swisspush.redisques.lua; import io.vertx.core.Handler; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.redis.RedisClient; import java.util.*; /** * Manages the lua scripts. * * @author https://github.com/mcweba [Marc-Andre Weber] */ public class LuaScriptManager { private RedisClient redisClient; private Map<LuaScript,LuaScriptState> luaScripts = new HashMap<>(); private Logger log = LoggerFactory.getLogger(LuaScriptManager.class); public LuaScriptManager(RedisClient redisClient){ this.redisClient = redisClient; LuaScriptState luaGetScriptState = new LuaScriptState(LuaScript.CHECK, redisClient); luaGetScriptState.loadLuaScript(new RedisCommandDoNothing(), 0); luaScripts.put(LuaScript.CHECK, luaGetScriptState); } /** * If the loglevel is trace and the logoutput in luaScriptState is false, then reload the script with logoutput and execute the RedisCommand. * If the loglevel is not trace and the logoutput in luaScriptState is true, then reload the script without logoutput and execute the RedisCommand. * If the loglevel is matching the luaScriptState, just execute the RedisCommand. * * @param redisCommand the redis command to execute * @param executionCounter current count of already passed executions */ private void executeRedisCommand(RedisCommand redisCommand, int executionCounter) { redisCommand.exec(executionCounter); } public void handleQueueCheck(String lastCheckExecKey, int checkInterval, Handler<Boolean> handler){ List<String> keys = Collections.singletonList(lastCheckExecKey); List<String> arguments = Arrays.asList( String.valueOf(System.currentTimeMillis()), String.valueOf(checkInterval) ); executeRedisCommand(new Check(keys, arguments, redisClient, handler), 0); } private class Check implements RedisCommand { private List<String> keys; private List<String> arguments; private Handler<Boolean> handler; private RedisClient redisClient; public Check(List<String> keys, List<String> arguments, RedisClient redisClient, final Handler<Boolean> handler) { this.keys = keys; this.arguments = arguments; this.redisClient = redisClient; this.handler = handler; } @Override public void exec(int executionCounter) { redisClient.evalsha(luaScripts.get(LuaScript.CHECK).getSha(), keys, arguments, event -> { if(event.succeeded()){ Long value = event.result().getLong(0); if (log.isTraceEnabled()) { log.trace("Check lua script got result: " + value); } handler.handle(value == 1L); } else { String message = event.cause().getMessage(); if(message != null && message.startsWith("NOSCRIPT")) { log.warn("Check script couldn't be found, reload it"); log.warn("amount the script got loaded: " + String.valueOf(executionCounter)); if(executionCounter > 10) { log.error("amount the script got loaded is higher than 10, we abort"); } else { luaScripts.get(LuaScript.CHECK).loadLuaScript(new Check(keys, arguments, redisClient, handler), executionCounter); } } else { log.error("Check request failed with message: " + message); } } }); } } }