@@ -5,74 +5,176 @@ package example_commands_test
55import (
66 "context"
77 "fmt"
8- "time"
98
109 "github.com/redis/go-redis/v9"
1110)
1211
1312// HIDE_END
1413
1514func ExampleClient_transactions () {
16- // STEP_START basic_trans
1715 ctx := context .Background ()
1816
1917 rdb := redis .NewClient (& redis.Options {
2018 Addr : "localhost:6379" ,
2119 Password : "" , // no password docs
2220 DB : 0 , // use default DB
2321 })
24-
2522 // REMOVE_START
26- rdb .Del (ctx , "RateCounter" )
23+ for i := 0 ; i < 5 ; i ++ {
24+ rdb .Del (ctx , fmt .Sprintf ("seat:%d" , i ))
25+ }
26+
27+ rdb .Del (ctx , "counter:1" , "counter:2" , "counter:3" , "shellpath" )
2728 // REMOVE_END
2829
29- setResult , err := rdb .Set (ctx , "RateCounter" , 0 , 0 ).Result ()
30+ // STEP_START basic_pipe
31+ pipe := rdb .Pipeline ()
32+
33+ for i := 0 ; i < 5 ; i ++ {
34+ pipe .Set (ctx , fmt .Sprintf ("seat:%v" , i ), fmt .Sprintf ("#%v" , i ), 0 )
35+ }
36+
37+ cmds , err := pipe .Exec (ctx )
3038
3139 if err != nil {
3240 panic (err )
3341 }
3442
35- fmt .Println (setResult ) // >>> OK
43+ for _ , c := range cmds {
44+ fmt .Printf ("%v;" , c .(* redis.StatusCmd ).Val ())
45+ }
46+
47+ fmt .Println ("" )
48+ // >>> OK;OK;OK;OK;OK;
3649
50+ pipe = rdb .Pipeline ()
51+
52+ get0Result := pipe .Get (ctx , "seat:0" )
53+ get3Result := pipe .Get (ctx , "seat:3" )
54+ get4Result := pipe .Get (ctx , "seat:4" )
55+
56+ cmds , err = pipe .Exec (ctx )
57+
58+ // The results are available only after the pipeline
59+ // has finished executing.
60+ fmt .Println (get0Result .Val ()) // >>> #0
61+ fmt .Println (get3Result .Val ()) // >>> #3
62+ fmt .Println (get4Result .Val ()) // >>> #4
63+ // STEP_END
64+
65+ // STEP_START basic_pipe_pipelined
66+ var pd0Result * redis.StatusCmd
67+ var pd3Result * redis.StatusCmd
68+ var pd4Result * redis.StatusCmd
69+
70+ cmds , err = rdb .Pipelined (ctx , func (pipe redis.Pipeliner ) error {
71+ pd0Result = (* redis .StatusCmd )(pipe .Get (ctx , "seat:0" ))
72+ pd3Result = (* redis .StatusCmd )(pipe .Get (ctx , "seat:3" ))
73+ pd4Result = (* redis .StatusCmd )(pipe .Get (ctx , "seat:4" ))
74+ return nil
75+ })
76+
77+ if err != nil {
78+ panic (err )
79+ }
80+
81+ // The results are available only after the pipeline
82+ // has finished executing.
83+ fmt .Println (pd0Result .Val ()) // >>> #0
84+ fmt .Println (pd3Result .Val ()) // >>> #3
85+ fmt .Println (pd4Result .Val ()) // >>> #4
86+ // STEP_END
87+
88+ // STEP_START basic_trans
3789 trans := rdb .TxPipeline ()
3890
39- // The values of `incrResult` and `expResult` are not available
40- // until the transaction has finished executing.
41- incrResult := trans .Incr (ctx , "RateCounter" )
42- expResult := trans .Expire (ctx , "RateCounter" , time .Second * 10 )
91+ trans .IncrBy (ctx , "counter:1" , 1 )
92+ trans .IncrBy (ctx , "counter:2" , 2 )
93+ trans .IncrBy (ctx , "counter:3" , 3 )
94+
95+ cmds , err = trans .Exec (ctx )
4396
44- cmdsExecuted , err := trans .Exec (ctx )
97+ for _ , c := range cmds {
98+ fmt .Println (c .(* redis.IntCmd ).Val ())
99+ }
100+ // >>> 1
101+ // >>> 2
102+ // >>> 3
103+ // STEP_END
104+
105+ // STEP_START basic_trans_txpipelined
106+ var tx1Result * redis.IntCmd
107+ var tx2Result * redis.IntCmd
108+ var tx3Result * redis.IntCmd
109+
110+ cmds , err = rdb .TxPipelined (ctx , func (trans redis.Pipeliner ) error {
111+ tx1Result = trans .IncrBy (ctx , "counter:1" , 1 )
112+ tx2Result = trans .IncrBy (ctx , "counter:2" , 2 )
113+ tx3Result = trans .IncrBy (ctx , "counter:3" , 3 )
114+ return nil
115+ })
45116
46117 if err != nil {
47118 panic (err )
48119 }
49120
50- // Values are now available.
51- fmt .Println (incrResult .Val ()) // >>> 1
52- fmt .Println (expResult .Val ()) // >>> true
53-
54- // You can also use the array of command data returned
55- // by the `Exec()` call.
56- fmt .Println (len (cmdsExecuted )) // >>> 2
57-
58- fmt .Printf ("%v: %v\n " ,
59- cmdsExecuted [0 ].Name (),
60- cmdsExecuted [0 ].(* redis.IntCmd ).Val (),
61- )
62- // >>> incr: 1
63-
64- fmt .Printf ("%v: %v\n " ,
65- cmdsExecuted [1 ].Name (),
66- cmdsExecuted [1 ].(* redis.BoolCmd ).Val (),
67- )
68- // >>> expire: true
121+ fmt .Println (tx1Result .Val ()) // >>> 2
122+ fmt .Println (tx2Result .Val ()) // >>> 4
123+ fmt .Println (tx3Result .Val ()) // >>> 6
124+ // STEP_END
125+
126+ // STEP_START trans_watch
127+ // Set initial value of `shellpath`.
128+ rdb .Set (ctx , "shellpath" , "/usr/syscmds/" , 0 )
129+
130+ const maxRetries = 1000
131+
132+ // Retry if the key has been changed.
133+ for i := 0 ; i < maxRetries ; i ++ {
134+ err := rdb .Watch (ctx ,
135+ func (tx * redis.Tx ) error {
136+ currentPath , err := rdb .Get (ctx , "shellpath" ).Result ()
137+ newPath := currentPath + ":/usr/mycmds/"
138+
139+ _ , err = tx .TxPipelined (ctx , func (pipe redis.Pipeliner ) error {
140+ pipe .Set (ctx , "shellpath" , newPath , 0 )
141+ return nil
142+ })
143+
144+ return err
145+ },
146+ "shellpath" ,
147+ )
148+
149+ if err == nil {
150+ // Success.
151+ break
152+ } else if err == redis .TxFailedErr {
153+ // Optimistic lock lost. Retry the transaction.
154+ continue
155+ } else {
156+ // Panic for any other error.
157+ panic (err )
158+ }
159+ }
160+
161+ fmt .Println (rdb .Get (ctx , "shellpath" ).Val ())
162+ // >>> /usr/syscmds/:/usr/mycmds/
69163 // STEP_END
70164
71165 // Output:
72- // OK
166+ // OK;OK;OK;OK;OK;
167+ // #0
168+ // #3
169+ // #4
170+ // #0
171+ // #3
172+ // #4
73173 // 1
74- // true
75174 // 2
76- // incr: 1
77- // expire: true
175+ // 3
176+ // 2
177+ // 4
178+ // 6
179+ // /usr/syscmds/:/usr/mycmds/
78180}
0 commit comments