Eldar
Eldar

Reputation: 10790

StackExchange.Redis Transaction chaining parameters

I'm trying to execute a basic transactional operation that contains two operations

  1. Get the length of a set scard MySet
  2. Pop the entire set with the given length : spop MySet len

I know it is possible to use smembers and del consecutively. But what I want to achieve is to get the output of the first operation and use it in the second operation and do it in a transaction. Here is what I tried so far:

var transaction = this.cacheClient.Db1.Database.CreateTransaction();
var itemLength = transaction.SetLengthAsync(key).ContinueWith(async lengthTask =>
{
  var length = await lengthTask;
  try
  {
       // here I want to pass the length argument
       return await transaction.SetPopAsync(key, length); // probably here transaction is already committed
      // so it never passes this line and no exceptions thrown.
  }
  catch (Exception ex)
  {
       throw;
  }

});

await transaction.ExecuteAsync();

Also, I tried the same thing with CreateBatch and get the same result. I'm currently using the workaround I mentioned above. I know it is also possible to evaluate a Lua script but I want to know is it possible with transactions or am I doing something terribly wrong.

Upvotes: 1

Views: 677

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062975

The nature of redis is that you cannot read data during multi/exec - you only get results when the exec runs, which means it isn't possible to use those results inside the multi. What you are attempting is kinda doomed. There are two ways of doing what you want here:

  1. Speculatively read what you need, then perform a multi/exec (transaction) block using that knowledge as a constraint, which SE.Redis will enforce inside a WATCH block; this is really complex and hard to get right, quite honestly
  2. Use Lua, meaning: ScriptEvaluate[Async], where you can do everything you want in a series of operations that execute contiguously on the server without competing with other connections

Option 2 is almost always the right way to do this, ever since it became possible.

Upvotes: 2

Related Questions