summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-redis/redis/tx.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-redis/redis/tx.go')
-rw-r--r--vendor/github.com/go-redis/redis/tx.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/vendor/github.com/go-redis/redis/tx.go b/vendor/github.com/go-redis/redis/tx.go
new file mode 100644
index 000000000..5ef89619b
--- /dev/null
+++ b/vendor/github.com/go-redis/redis/tx.go
@@ -0,0 +1,96 @@
+package redis
+
+import (
+ "github.com/go-redis/redis/internal"
+ "github.com/go-redis/redis/internal/pool"
+)
+
+// Redis transaction failed.
+const TxFailedErr = internal.RedisError("redis: transaction failed")
+
+// Tx implements Redis transactions as described in
+// http://redis.io/topics/transactions. It's NOT safe for concurrent use
+// by multiple goroutines, because Exec resets list of watched keys.
+// If you don't need WATCH it is better to use Pipeline.
+type Tx struct {
+ statefulCmdable
+ baseClient
+}
+
+func (c *Client) newTx() *Tx {
+ tx := Tx{
+ baseClient: baseClient{
+ opt: c.opt,
+ connPool: pool.NewStickyConnPool(c.connPool.(*pool.ConnPool), true),
+ },
+ }
+ tx.setProcessor(tx.Process)
+ return &tx
+}
+
+func (c *Client) Watch(fn func(*Tx) error, keys ...string) error {
+ tx := c.newTx()
+ if len(keys) > 0 {
+ if err := tx.Watch(keys...).Err(); err != nil {
+ _ = tx.Close()
+ return err
+ }
+ }
+ firstErr := fn(tx)
+ if err := tx.Close(); err != nil && firstErr == nil {
+ firstErr = err
+ }
+ return firstErr
+}
+
+// close closes the transaction, releasing any open resources.
+func (c *Tx) Close() error {
+ _ = c.Unwatch().Err()
+ return c.baseClient.Close()
+}
+
+// Watch marks the keys to be watched for conditional execution
+// of a transaction.
+func (c *Tx) Watch(keys ...string) *StatusCmd {
+ args := make([]interface{}, 1+len(keys))
+ args[0] = "WATCH"
+ for i, key := range keys {
+ args[1+i] = key
+ }
+ cmd := NewStatusCmd(args...)
+ c.Process(cmd)
+ return cmd
+}
+
+// Unwatch flushes all the previously watched keys for a transaction.
+func (c *Tx) Unwatch(keys ...string) *StatusCmd {
+ args := make([]interface{}, 1+len(keys))
+ args[0] = "UNWATCH"
+ for i, key := range keys {
+ args[1+i] = key
+ }
+ cmd := NewStatusCmd(args...)
+ c.Process(cmd)
+ return cmd
+}
+
+func (c *Tx) Pipeline() Pipeliner {
+ pipe := Pipeline{
+ exec: c.pipelineExecer(c.txPipelineProcessCmds),
+ }
+ pipe.setProcessor(pipe.Process)
+ return &pipe
+}
+
+// Pipelined executes commands queued in the fn in a transaction
+// and restores the connection state to normal.
+//
+// When using WATCH, EXEC will execute commands only if the watched keys
+// were not modified, allowing for a check-and-set mechanism.
+//
+// Exec always returns list of commands. If transaction fails
+// TxFailedErr is returned. Otherwise Exec returns error of the first
+// failed command or nil.
+func (c *Tx) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
+ return c.Pipeline().pipelined(fn)
+}