using System; using System.Collections.Generic; using System.Collections.Concurrent; using System.Linq; using System.Text; using System.Threading.Tasks; using StackExchange.Redis; namespace ServerCore; //============================================================================================= // Server-side transactional scripting in Redis // //============================================================================================= public abstract class RedisWithLuaScriptExecutorBase { private readonly RedisConnectorBase m_connector; private readonly ConcurrentDictionary m_loaded_lua_scripts = new(); public RedisWithLuaScriptExecutorBase(RedisConnectorBase connector) { m_connector = connector; } public async Task tryLoadLuaScriptToRedisServer(string scriptName, string luaScript) { var err_msg = string.Empty; try { if (true == m_loaded_lua_scripts.ContainsKey(scriptName)) { return true; } var multiplexer = m_connector.getConnectionMultiplexer(); NullReferenceCheckHelper.throwIfNull(multiplexer, () => $"multiplexer is null !!!"); var end_points = multiplexer.GetEndPoints(); NullReferenceCheckHelper.throwIfNull(end_points, () => $"end_points is null !!!"); var curr_server = multiplexer.GetServer(end_points[0]); NullReferenceCheckHelper.throwIfNull(curr_server, () => $"curr_server is null !!!"); var prepared_lug_script = LuaScript.Prepare(luaScript); NullReferenceCheckHelper.throwIfNull(prepared_lug_script, () => $"prepared_lug_script is null !!!"); var uploaded_lua_script = await prepared_lug_script.LoadAsync(curr_server); NullReferenceCheckHelper.throwIfNull(uploaded_lua_script, () => $"uploaded_lua_script is null !!!"); m_loaded_lua_scripts[scriptName] = uploaded_lua_script; } catch (Exception e) { err_msg = $"Exception !!!, Failed to function in tryLoadScriptAsync() !!! : exception:{e}"; Log.getLogger().error(err_msg); return false; } return true; } public async Task<(bool, RedisResult?)> tryExecuteLuaScriptAsync(string scriptName, RedisKey[] keys, RedisValue[]? args = null) { RedisResult? redis_result = null; var err_msg = string.Empty; try { var connected_redis_db = m_connector.getDatabase(); NullReferenceCheckHelper.throwIfNull(connected_redis_db, () => $"connected_redis_db is null !!!"); if (false == m_loaded_lua_scripts.TryGetValue(scriptName, out var found_lua_script)) { err_msg = $"Not found LuaScript !!! : scriptName:{scriptName}"; return (false, null); } var script = found_lua_script.ExecutableScript; redis_result = await connected_redis_db.ScriptEvaluateAsync(script, keys, args); } catch (Exception e) { err_msg = $"Exception !!!, Failed to ScriptEvaluateAsync() !!! : exception:{e} - LuaScriptName:{scriptName}"; Log.getLogger().error(err_msg); return (false, null); } return (true, redis_result); } }