StackExchange / StackExchange.Redis

General purpose redis client
https://stackexchange.github.io/StackExchange.Redis/
Other
5.86k stars 1.5k forks source link

When a transaction is used, there is no response to the command #2600

Closed henrydingchina closed 7 months ago

henrydingchina commented 8 months ago

version:2.6.122

When I execute the following method, I can't get a task response or timeout, and there is no error after executing ListLeftPushAsync, why do I only use 10 pieces of data for testing?

  public async Task<bool> InsertCameraDetection(string key, List<CameraDetectionBto> values)
        {
            try
            {
                var transaction = m_db.CreateTransaction();
                var kv = values.ToDictionary(x => new RedisKey(x.Key()), x => new RedisValue(JsonConvert.SerializeObject(x)));
                var stringKey = kv.Select(x => new RedisValue(x.Key)).ToArray();
                var v = kv.ToArray();

                await transaction.ListLeftPushAsync(key, stringKey);
                await transaction.StringSetAsync(v);
                var committed = transaction.Execute();
                return committed;
            }
            catch (Exception ex)
            {
                _logger.Warn("Occur Exception:", ex);
                return false;
            }
      }
NickCraver commented 8 months ago

For a transaction, the individual operations aren't sent until the .Execute() (or .ExecuteAsync()), so if you await them you're stuck there forever awaiting something that won't complete.

Basically you want to remove the awaits here :)

mgravell commented 8 months ago

I need to write an analyzer for this. Or better: just mark that API [Obsolete("Seriously, just use Lua, it'll keep you saner")]

But; to clarify usage:

Basically you want to remove the awaits here :)

It is a little more nuanced than that; you need to delay those awaits until after execution, in the case that you care about the responses, i.e.

var pending = tran.WhateverAsync(...);
// ... other things
await tran.ExecuteAsync();
var result = await penidng;

But to emphasize: in most cases, it'll be easier and more powerful to use Lua

NickCraver commented 7 months ago

Closing out to tidy up here, advice above!