Skip to content

Commit

Permalink
DOC-4560 added pipe/transaction examples
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-stark-redis committed Dec 6, 2024
1 parent 59007b8 commit 004659d
Showing 1 changed file with 136 additions and 34 deletions.
170 changes: 136 additions & 34 deletions doctests/pipe_trans_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,74 +5,176 @@ package example_commands_test
import (
"context"
"fmt"
"time"

"github.com/redis/go-redis/v9"
)

// HIDE_END

func ExampleClient_transactions() {
// STEP_START basic_trans
ctx := context.Background()

rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})

// REMOVE_START
rdb.Del(ctx, "RateCounter")
for i := 0; i < 5; i++ {
rdb.Del(ctx, fmt.Sprintf("seat:%d", i))
}

rdb.Del(ctx, "counter:1", "counter:2", "counter:3", "shellpath")
// REMOVE_END

setResult, err := rdb.Set(ctx, "RateCounter", 0, 0).Result()
// STEP_START basic_pipe
pipe := rdb.Pipeline()

for i := 0; i < 5; i++ {
pipe.Set(ctx, fmt.Sprintf("seat:%v", i), fmt.Sprintf("#%v", i), 0)
}

cmds, err := pipe.Exec(ctx)

if err != nil {
panic(err)
}

fmt.Println(setResult) // >>> OK
for _, c := range cmds {
fmt.Printf("%v;", c.(*redis.StatusCmd).Val())
}

fmt.Println("")
// >>> OK;OK;OK;OK;OK;

pipe = rdb.Pipeline()

get0Result := pipe.Get(ctx, "seat:0")
get3Result := pipe.Get(ctx, "seat:3")
get4Result := pipe.Get(ctx, "seat:4")

cmds, err = pipe.Exec(ctx)

// The results are available only after the pipeline
// has finished executing.
fmt.Println(get0Result.Val()) // >>> #0
fmt.Println(get3Result.Val()) // >>> #3
fmt.Println(get4Result.Val()) // >>> #4
// STEP_END

// STEP_START basic_pipe_pipelined
var pd0Result *redis.StatusCmd
var pd3Result *redis.StatusCmd
var pd4Result *redis.StatusCmd

cmds, err = rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
pd0Result = (*redis.StatusCmd)(pipe.Get(ctx, "seat:0"))
pd3Result = (*redis.StatusCmd)(pipe.Get(ctx, "seat:3"))
pd4Result = (*redis.StatusCmd)(pipe.Get(ctx, "seat:4"))
return nil
})

if err != nil {
panic(err)
}

// The results are available only after the pipeline
// has finished executing.
fmt.Println(pd0Result.Val()) // >>> #0
fmt.Println(pd3Result.Val()) // >>> #3
fmt.Println(pd4Result.Val()) // >>> #4
// STEP_END

// STEP_START basic_trans
trans := rdb.TxPipeline()

// The values of `incrResult` and `expResult` are not available
// until the transaction has finished executing.
incrResult := trans.Incr(ctx, "RateCounter")
expResult := trans.Expire(ctx, "RateCounter", time.Second*10)
trans.IncrBy(ctx, "counter:1", 1)
trans.IncrBy(ctx, "counter:2", 2)
trans.IncrBy(ctx, "counter:3", 3)

cmds, err = trans.Exec(ctx)

cmdsExecuted, err := trans.Exec(ctx)
for _, c := range cmds {
fmt.Println(c.(*redis.IntCmd).Val())
}
// >>> 1
// >>> 2
// >>> 3
// STEP_END

// STEP_START basic_trans_txpipelined
var tx1Result *redis.IntCmd
var tx2Result *redis.IntCmd
var tx3Result *redis.IntCmd

cmds, err = rdb.TxPipelined(ctx, func(trans redis.Pipeliner) error {
tx1Result = trans.IncrBy(ctx, "counter:1", 1)
tx2Result = trans.IncrBy(ctx, "counter:2", 2)
tx3Result = trans.IncrBy(ctx, "counter:3", 3)
return nil
})

if err != nil {
panic(err)
}

// Values are now available.
fmt.Println(incrResult.Val()) // >>> 1
fmt.Println(expResult.Val()) // >>> true

// You can also use the array of command data returned
// by the `Exec()` call.
fmt.Println(len(cmdsExecuted)) // >>> 2

fmt.Printf("%v: %v\n",
cmdsExecuted[0].Name(),
cmdsExecuted[0].(*redis.IntCmd).Val(),
)
// >>> incr: 1

fmt.Printf("%v: %v\n",
cmdsExecuted[1].Name(),
cmdsExecuted[1].(*redis.BoolCmd).Val(),
)
// >>> expire: true
fmt.Println(tx1Result.Val()) // >>> 2
fmt.Println(tx2Result.Val()) // >>> 4
fmt.Println(tx3Result.Val()) // >>> 6
// STEP_END

// STEP_START trans_watch
// Set initial value of `shellpath`.
rdb.Set(ctx, "shellpath", "/usr/syscmds/", 0)

const maxRetries = 1000

// Retry if the key has been changed.
for i := 0; i < maxRetries; i++ {
err := rdb.Watch(ctx,
func(tx *redis.Tx) error {
currentPath, err := rdb.Get(ctx, "shellpath").Result()
newPath := currentPath + ":/usr/mycmds/"

_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
pipe.Set(ctx, "shellpath", newPath, 0)
return nil
})

return err
},
"shellpath",
)

if err == nil {
// Success.
break
} else if err == redis.TxFailedErr {
// Optimistic lock lost. Retry the transaction.
continue
} else {
// Panic for any other error.
panic(err)
}
}

fmt.Println(rdb.Get(ctx, "shellpath").Val())
// >>> /usr/syscmds/:/usr/mycmds/
// STEP_END

// Output:
// OK
// OK;OK;OK;OK;OK;
// #0
// #3
// #4
// #0
// #3
// #4
// 1
// true
// 2
// incr: 1
// expire: true
// 3
// 2
// 4
// 6
// /usr/syscmds/:/usr/mycmds/
}

0 comments on commit 004659d

Please sign in to comment.