Redix.transaction_pipeline
transaction_pipeline
, go back to Redix module for more information.
Specs
transaction_pipeline(connection(), [command()], keyword()) :: {:ok, [Redix.Protocol.redis_value()]} | {:error, atom() | Redix.Error.t() | Redix.ConnectionError.t()}
Executes a MULTI
/EXEC
transaction.
Redis supports something akin to transactions. It works by sending a MULTI
command,
then some commands, and then an EXEC
command. All the commands after MULTI
are
queued until EXEC
is issued. When EXEC
is issued, all the responses to the queued
commands are returned in a list.
This function accepts the same options as pipeline/3
.
Examples
To run a MULTI
/EXEC
transaction in one go, use this function and pass a list of
commands to use in the transaction:
iex> Redix.transaction_pipeline(conn, [["SET", "mykey", "foo"], ["GET", "mykey"]])
{:ok, ["OK", "foo"]}
Problems with transactions
There's an inherent problem with Redix's architecture and MULTI
/EXEC
transaction.
A Redix process is a single connection to Redis that can be used by many clients. If
a client A sends MULTI
and client B sends a command before client A sends EXEC
,
client B's command will be part of the transaction. This is intended behaviour, but
it might not be what you expect. This is why transaction_pipeline/3
exists: this function
wraps commands
in MULTI
/EXEC
but sends all in a pipeline. Since everything
is sent in the pipeline, it's sent at once on the connection and no commands can
end up in the middle of the transaction.
Running MULTI
/EXEC
transactions manually
There are still some cases where you might want to start a transaction with MULTI
,
then send commands from different processes that you actively want to be in the
transaction, and then send an EXEC
to run the transaction. It's still fine to do
this with command/3
or pipeline/3
, but remember what explained in the section
above. If you do this, do it in an isolated connection (open a new one if necessary)
to avoid mixing things up.