andreycha
andreycha

Reputation: 405

StackExchange.Redis: couple of questions about transactions

I've got several question about using transactions from StackExchange.Redis:

  1. Is it allowed to execute commands in transaction which could potentially target different nodes in cluster environment? Say, first command's key has {1} hashtag and second command's key has {2} hashtag.
  2. When does transaction's Execute()/ExecuteAsync() returns false? Only when set conditions were not met? Could it return false if there were no conditions set?
  3. If some network or internal Redis error occur, will Execute()/ExecuteAsync() throw or just return false? Should I also check commands' tasks (assuming that commands are fully correct and normally are not expected to throw) or they will just be cancelled?

Unfortunately the doc doesn't explain #2 and #3 in details.

Upvotes: 12

Views: 3934

Answers (2)

andreycha
andreycha

Reputation: 405

I've digged a bit into StackExchange.Redis source code and played with the driver, here are my observations:

  • no actual interaction happens when you call op methods on ITransaction instance
  • driver starts talking to Redis only when you call Execute()/ExecuteAsync()

The answers seem to be the following:

  1. As @royi-mindel mentioned, all keys in transaction must target the same slot. Otherwise you get "Multi-key operations must involve a single slot" exception.
  2. Execute()/ExecuteAsync() returns false in two cases: when transaction was discarded because conditions were not met, and when driver failed to queue the command (for example because of server OOM). All command tasks will be marked as canceled. Also Execute()/ExecuteAsync() does not return false if one of the commands failed during execution (for example, because of wrong type operation).
  3. In case some network problem occurs, Execute()/ExecuteAsync() will throw an exception and all commands tasks will remain in "waiting for activation" state.

To sum it up, command tasks should only be checked if Execute()/ExecuteAsync() returned true: every task will either contain a result or an error (see Exception property).

Upvotes: 8

Royi Mindel
Royi Mindel

Reputation: 1258

  1. "Redis Cluster implements all the single key commands available in the non-distributed version of Redis. Commands performing complex multi-key operations like Set type unions or intersections are implemented as well as long as the keys all belong to the same node." https://redis.io/topics/cluster-spec

You can't send multi-key operations with multi cluster keys.

  1. "During a transaction it is possible to encounter two kind of command errors:

A command may fail to be queued, so there may be an error before EXEC is called. For instance the command may be syntactically wrong (wrong number of arguments, wrong command name, ...), or there may be some critical condition like an out of memory condition (if the server is configured to have a memory limit using the maxmemory directive).

A command may fail after EXEC is called, for instance since we performed an operation against a key with the wrong value (like calling a list operation against a string value)." https://redis.io/topics/transactions

  1. In .Net when you run a task, If an unhandled exception is thrown within - it will not bubble outside of the task unless you use taskInstance.Wait() - then you will get an AggregateException and need to check InnerExceptions for the actual exceptions.

Upvotes: 2

Related Questions