Is it possible to run lua script on particular server endpoint using StackExchange.Redis server.Execute ( ExecuteAsync) call?
currently using following code:
public async Task<bool> ExecuteScriptAsync(string scriptName, object[] keyArgs = null, object[] valueArgs = null)
{
List<byte[]> scriptHashes;
_logger.Log(LogLevel.Information, $"Evaluating script: {scriptName}");
if (!_scriptHashes.TryGetValue(scriptName, out scriptHashes))
{
throw new ArgumentException($"Requested script {scriptName} was not found");
}
RedisValue[] redisValues = valueArgs == null ? null : Array.ConvertAll(valueArgs, RedisValueHelper.ToRedisValue);
RedisKey[] redisKeys = keyArgs == null
? null
: Array.ConvertAll(keyArgs,
source =>
{
if (source == null)
{
return default;
}
return (RedisKey)source.ToString();
});
string script = GetScriptByName(scriptName);
foreach (EndPoint endPoint in _connectionMultiplexer.GetEndPoints())
{
IServer server = _connectionMultiplexer.GetServer(endPoint);
if (server != null && server.IsConnected && !server.IsReplica)
{
_logger.Log(LogLevel.Information, $"Executing script {scriptName} on endpoint: {server.EndPoint}");
scriptTasks.Add(server.ExecuteAsync("EVAL", script, 0, redisKeys, redisValues));
}
}
foreach (RedisResult result in await Task.WhenAll(scriptTasks))
{
_logger.Log(LogLevel.Information, $"Got script eval result:{result}");
}
return true;
}
but it seems to be not working. It fails with TimeoutException.
StackExchange.Redis.RedisTimeoutException: Timeout awaiting response (outbound=0KiB, inbound=0KiB, 5360ms elapsed, timeout is 5000ms), command=UNKNOWN, next: EVAL, inst: 0, qu: 0, qs: 1, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: <server_name>:6379, mc: 1/1/0, mgr: 10 of 10 available, clientName: CLIENT, IOCP: (Busy=0,Free=1000,Min=12,Max=1000), WORKER: (Busy=1,Free=32766,Min=12,Max=32767), v: 2.2.88.56325 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
I want to execute the script on every primary node of redis cluster. The lua script remove keys by specified key prefix:
local keys = {};
local done = false;
local cursor = "0";
local numDeleted = 0;
local unlinkKey = function(key)
local result;
local num = redis.pcall("UNLINK", key);
if type(num) == "table" then
result = 0;
else
result = num;
end
return result;
end
repeat
local result = redis.call("SCAN", cursor, "match", KEYS[1], "count", 10000)
cursor = result[1];
keys = result[2];
for i, key in ipairs(keys) do
numDeleted = numDeleted + unlinkKey(key);
end
if cursor == "0" then
done = true;
end
until done
return numDeleted;
db.ScriptEvaluate doesn't work properly in case of cluster as it doesn't execute it on all nodes but rather on some random one.
Thanks.