I'm trying to use StackExchange.Redis to implement transactional Add Or Update logic. I've looked at the https://stackexchange.github.io/StackExchange.Redis/Transactions.html example on GitHub but this refers to an "add if not exists" process, which is really only part of the story.
My requirement is it "Add if cache item does not exist and update if it has not changed" (i.e. optimistic concurrency). This example helped https://github.com/StackExchange/StackExchange.Redis/issues/885 but it only uses one condition, as does the example for transaction on Github.
My tests of a redis transaction suggests that you cannot add multiple conditions, therefore this approach seems to work:
var committed = await _redisDatabase.StringSetAsync(key, value, expiry, When.NotExists, flags);
if (committed)
{
return committed;
}
var txn = _redisDatabase.CreateTransaction();
txn.AddCondition(Condition.StringEqual(key, value));
txn.StringSetAsync(key, value, expiry, when, flags);
committed = await txn.ExecuteAsync();
return committed;
i.e. assume it does not exist, attempt update if it does... The When.NotExists always needs to be called as the second section could fail because the object has changed or that it doesn't exist.. so you need the first call so that you know the second has failed due to stale stale.
This makes a SETNX on the first call and then the additional WATCH, GET, MULTI and SET commands....is there anyway to combine this into one Redis transaction?