garnet icon indicating copy to clipboard operation
garnet copied to clipboard

Bug: Incompatibility with StackExchange Client's txn call for ExecuteAsync command

Open hamdaankhalid opened this issue 1 year ago • 1 comments

Describe the bug

Seeing some unexpected behavior in Garnet when used with redis stack exchange client. Calling ExecuteAsync (for being able to send commands raw) in a transaction causes the transaction to abort.

Using the below given program which passes in Redis but fails in Garnet, I was able to assert the issue is with garnet and not the client. Also attaching the encountered exception. Ran it in debugger and saw the server is processing a select statement inside the multi exec block which is not supposed to happen.

   at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server, T defaultValue) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 2103
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server, T defaultValue) in /_/src/StackExchange.Redis/RedisBase.cs:line 62
   at StackExchange.Redis.RedisTransaction.Execute(CommandFlags flags) in /_/src/StackExchange.Redis/RedisTransaction.cs:line 50
   at StackExcgTst.Program.Main(String[] args) in C:\Users\hkhalid\repos\personal\StackExcgTst\Program.cs:line 27

Steps to reproduce the bug

  1. Use below example program against Garnet and it should throw and abort transaction exception:
using StackExchange.Redis;
using System.Threading.Tasks;

namespace StackExcgTst;

class Program
{
    static void Main(string[] args)
    {
        // Connect to Redis server on localhost
        var redis = ConnectionMultiplexer.Connect(args[0]);

        // Get a reference to the default Redis database (index 0)
        var db = redis.GetDatabase();

        // Start a transaction
        ITransaction tran = db.CreateTransaction();

        // Add a single SET command to the transaction
        var setTask = tran.ExecuteAsync("SET", ["key", "val"]);

        // This works
        // var setTask = tran.StringSetAsync("key", "val"); 

        // Commit the transaction
        bool committed = tran.Execute();

        // Check if the transaction was successfully committed
        if (committed)
        {
            Console.WriteLine("Transaction committed successfully.");
        }
        else
        {
            Console.WriteLine("Transaction failed.");
        }

        // Fetch the value of the key from Redis to verify
        var value = db.StringGet("key");
        Console.WriteLine($"Value of 'key' is: {value}");
    }
}

Expected behavior

When the same above program is used with Redis it successfully completes, and the transaction is not aborted.

Screenshots

No response

Release version

No response

IDE

No response

OS version

No response

Additional context

No response

hamdaankhalid avatar Oct 10 '24 22:10 hamdaankhalid

the server is processing a select statement inside the multi exec block

this part sounds like a client problem, why is a select being sent? in any case, the server should probably handle it gracefully.

badrishc avatar Oct 10 '24 23:10 badrishc

Ping @hamdaankhalid - do you have a PR for this yet? thanks!

badrishc avatar Jan 14 '25 19:01 badrishc