go-transaction-manager
125 строк · 2.4 Кб
1//go:build with_real_db
2// +build with_real_db
3
4package pgxv4_test
5
6import (
7"context"
8"fmt"
9
10"github.com/jackc/pgx/v4/pgxpool"
11
12trmpgx "github.com/avito-tech/go-transaction-manager/drivers/pgxv4/v2"
13
14"github.com/avito-tech/go-transaction-manager/trm/v2/manager"
15)
16
17// Example demonstrates the implementation of the Repository pattern by trm.Manager.
18func Example() {
19ctx := context.Background()
20
21uri := fmt.Sprintf("postgres://%s:%s@%s:%d/%s",
22"user", "pass", "localhost", 5432, "db",
23)
24
25pool, err := pgxpool.Connect(ctx, uri)
26checkErr(err)
27
28defer pool.Close()
29
30sqlStmt := `CREATE TABLE IF NOT EXISTS users_v4 (user_id SERIAL, username TEXT)`
31_, err = pool.Exec(ctx, sqlStmt)
32checkErr(err, sqlStmt)
33
34r := newRepo(pool, trmpgx.DefaultCtxGetter)
35trManager := manager.Must(trmpgx.NewDefaultFactory(pool))
36
37u := &user{
38Username: "username",
39}
40
41err = trManager.Do(ctx, func(ctx context.Context) error {
42if err := r.Save(ctx, u); err != nil {
43return err
44}
45
46return trManager.Do(ctx, func(ctx context.Context) error {
47u.Username = "new_username"
48
49return r.Save(ctx, u)
50})
51})
52checkErr(err)
53
54userFromDB, err := r.GetByID(ctx, u.ID)
55checkErr(err)
56
57fmt.Println(userFromDB)
58
59// Output: &{1 new_username}
60}
61
62type repo struct {
63db *pgxpool.Pool
64getter *trmpgx.CtxGetter
65}
66
67func newRepo(db *pgxpool.Pool, c *trmpgx.CtxGetter) *repo {
68repo := &repo{
69db: db,
70getter: c,
71}
72
73return repo
74}
75
76type user struct {
77ID int64
78Username string
79}
80
81func (r *repo) GetByID(ctx context.Context, id int64) (*user, error) {
82query := `SELECT * FROM users_v4 WHERE user_id=$1`
83
84conn := r.getter.DefaultTrOrDB(ctx, r.db)
85row := conn.QueryRow(ctx, query, id)
86
87user := &user{}
88
89err := row.Scan(&user.ID, &user.Username)
90if err != nil {
91return nil, err
92}
93
94return user, nil
95}
96
97func (r *repo) Save(ctx context.Context, u *user) error {
98isNew := u.ID == 0
99conn := r.getter.DefaultTrOrDB(ctx, r.db)
100
101if !isNew {
102query := `UPDATE users_v4 SET username = $1 WHERE user_id = $2`
103
104if _, err := conn.Exec(ctx, query, u.Username, u.ID); err != nil {
105return err
106}
107
108return nil
109}
110
111query := `INSERT INTO users_v4 (username) VALUES ($1) RETURNING user_id`
112
113err := conn.QueryRow(ctx, query, u.Username).Scan(&u.ID)
114if err != nil {
115return err
116}
117
118return nil
119}
120
121func checkErr(err error, args ...interface{}) {
122if err != nil {
123panic(fmt.Sprint(append([]interface{}{err}, args...)...))
124}
125}
126