StackExchange / StackExchange/StackExchange.Redis
EVALSHA isn't working within transaction.
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 6.2k
- Forks
- 1.6k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 43
Description
I have create a LUA script to execute within a Transaction with other native command functions.
When I run the LUA script without transaction, it works as expected and EVALSHA get called always.
But when I wrap the same LUA script with same key & values and execute in a transaction (with or without other command functions), the framework sends script for every execution. EVAL gets called on script always.
Is this an expected behaviour or am I doing from wrong? @NickCraver @mgravell
Any suggessions to use EVALSHA in Transaction without sending script everytime?
References:-------
Below are MONITOR logs with NO Transaction:
1693207783.585817 [0 122.160.68.144:57986] "SELECT" "0"
1693207783.585817 [0 122.160.68.144:57986] "SCRIPT" "LOAD" "MY_LUA_SCRIPT"
1693207784.861812 [0 122.160.68.144:57986] "EVALSHA" "5092f92c0e62b72c3bf6539ab62a79fefc836395" "1" "{u:425}:pd" "{u:425}:pd" "$.logdt" "\"28-08-2023 12:59:45\""
1693207784.977812 [0 122.160.68.144:56816] "ping"
1693207786.137807 [0 122.160.68.144:57986] "EVALSHA" "5092f92c0e62b72c3bf6539ab62a79fefc836395" "1" "{u:425}:pd" "{u:425}:pd" "$.logdt" "\"28-08-2023 12:59:46\""
1693207788.525797 [0 122.160.68.144:57989] "PING"
1693207788.537797 [0 122.160.68.144:57988] "PING"
Below are MONITOR logs with Transaction:
1693207779.461834 [0 122.160.68.144:58003] "PING"
1693207779.757833 [0 122.160.68.144:57986] "MULTI"
1693207779.757833 [0 122.160.68.144:57986] "EVAL" "MY_LUA_SCRIPT"
1693207779.757833 [0 122.160.68.144:57986] "SELECT" "0"
1693207779.757833 [0 122.160.68.144:57986] "EXEC"
1693207780.473830 [0 122.160.68.144:58004] "PING"
1693207781.029828 [0 122.160.68.144:57986] "SELECT" "0"
1693207781.029828 [0 122.160.68.144:57986] "MULTI"
1693207781.029828 [0 122.160.68.144:57986] "EVAL" "MY_LUA_SCRIPT"
1693207781.029828 [0 122.160.68.144:57986] "SELECT" "0"
1693207781.029828 [0 122.160.68.144:57986] "EXEC"
1693207782.309823 [0 122.160.68.144:57986] "SELECT" "0"
1693207782.309823 [0 122.160.68.144:57986] "MULTI"
1693207782.309823 [0 122.160.68.144:57986] "EVAL" "MY_LUA_SCRIPT"
1693207782.309823 [0 122.160.68.144:57986] "SELECT" "0"
1693207782.309823 [0 122.160.68.144:57986] "EXEC"
1693207783.293819 [0 122.160.68.144:57970] "PING"
Extension function JsonSC_SetAsync:
public static async Task<bool> JsonSC_SetAsync(this ITransaction _db, RedisKey a_key, string a_path, object a_value, CommandFlags a_flags = CommandFlags.None)
{
List<RedisValue> list = new List<RedisValue> { a_path, (RedisValue)JsonConvert.SerializeObject(a_value) };
LuaScript l_sc = LuaScript.Prepare(SCRIPT__SET);
RedisResult l_rr = (await _db.ScriptEvaluateAsync(l_sc, new { key = a_key, path = a_path, value = JsonConvert.SerializeObject(a_value) }));
return l_rr.OKtoBoolean();
}
My test function for WITH Transaction:
async void TestMeWithTransaction()
{
await Task.Delay(10000);
Logger.Error("WithTransaction--START");
RedisConnection l_conn = RedisHandlerCommands.Default.GetConnection();
ITransaction l_trans = l_conn.Database.CreateTransaction();
l_trans.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
bool l_isSuccess = await l_trans.ExecuteAsync();
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
await Task.Delay(5000);
l_trans.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
l_isSuccess = await l_trans.ExecuteAsync();
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
await Task.Delay(5000);
l_trans.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
l_isSuccess = await l_trans.ExecuteAsync();
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
Logger.Error("WithTransaction--END");
TestMeNoTransaction();
}
My test function for WITH NO Transaction:
async void TestMeNoTransaction()
{
await Task.Delay(1000);
Logger.Error("NoTransaction--START");
RedisConnection l_conn = RedisHandlerCommands.Default.GetConnection();
bool l_isSuccess = await l_conn.Database.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
await Task.Delay(1000);
l_isSuccess = await l_conn.Database.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
await Task.Delay(1000);
l_isSuccess = await l_conn.Database.JsonSC_SetAsync("{u:425}:pd", "$.logdt", DateTime.Now.ToString());
Logger.Error("IsSuccess: {l_isSuccess}", l_isSuccess);
Logger.Error("NoTransaction--STARTEND");
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the JsonSC_SetAsync extension and the TestMeWithTransaction and TestMeNoTransaction functions shown in the issue; inspect how ITransaction.ScriptEvaluateAsync is queued and compare the MONITOR traces for EVAL versus EVALSHA. Done means establishing whether transaction execution should reuse the script SHA and, if a change is warranted, covering the observed behavior with a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, redis
- Domain
- database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100