mirror of
https://github.com/redis/go-redis.git
synced 2025-04-16 09:23:06 +03:00
* chore: extract benchmark tests * wip * enable pubsub tests * enable ring tests * stop tests with build redis from source * start all tests * mix of makefile and action * add sentinel configs * fix example test * stop debug on re * wip * enable gears for redis 7.2 * wip * enable sentinel, they are expected to fail * fix: linter configuration * chore: update re versions * return older redis enterprise version * add basic codeql * wip: increase timeout, focus only sentinel tests * sentinels with docker network host * enable all tests * fix flanky test * enable example tests * tidy docker compose * add debug output * stop shutingdown masters * don't test sentinel for re * skip unsuported addscores * Update README bump go version in CI * Update README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update CONTRIBUTING.md add information about new test setup --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
183 lines
3.7 KiB
Go
183 lines
3.7 KiB
Go
// EXAMPLE: pipe_trans_tutorial
|
|
// HIDE_START
|
|
package example_commands_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// HIDE_END
|
|
|
|
func ExampleClient_transactions() {
|
|
ctx := context.Background()
|
|
|
|
rdb := redis.NewClient(&redis.Options{
|
|
Addr: "localhost:6379",
|
|
Password: "", // no password docs
|
|
DB: 0, // use default DB
|
|
})
|
|
// REMOVE_START
|
|
// make sure we are working with fresh database
|
|
rdb.FlushDB(ctx)
|
|
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
|
|
|
|
// 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)
|
|
}
|
|
|
|
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()
|
|
|
|
trans.IncrBy(ctx, "counter:1", 1)
|
|
trans.IncrBy(ctx, "counter:2", 2)
|
|
trans.IncrBy(ctx, "counter:3", 3)
|
|
|
|
cmds, 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)
|
|
}
|
|
|
|
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;
|
|
// #0
|
|
// #3
|
|
// #4
|
|
// #0
|
|
// #3
|
|
// #4
|
|
// 1
|
|
// 2
|
|
// 3
|
|
// 2
|
|
// 4
|
|
// 6
|
|
// /usr/syscmds/:/usr/mycmds/
|
|
}
|