/
repository.go
77 lines (63 loc) · 1.54 KB
/
repository.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package storage
import (
"context"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Repository struct {
client *client
}
type client struct {
db *gorm.DB
}
// NewRepository sets up the database connections using the configuration in the
// process's environment variables. This should be called just once per port
// instance.
func NewRepository(ctx context.Context, config *Config) (*Repository, error) {
client, err := newClient(ctx, config)
if err != nil {
return nil, err
}
return &Repository{
client: client,
}, nil
}
func newClient(ctx context.Context, config *Config) (*client, error) {
dsn := "root:root@tcp(127.0.0.1:3306)/open_balance?charset=utf8mb4&parseTime=True" // TODO: move config outside
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
err = db.AutoMigrate(&userModel{}, &rootAccountModel{}, &balanceAccountModel{}, &transactionModel{})
if err != nil {
return nil, err
}
return &client{
db: db,
}, nil
}
func (r *Repository) TxnExec(ctx context.Context, f func(ctxWithTxn context.Context) (interface{}, error)) (interface{}, error) {
tx := r.client.db.Begin()
defer func() {
r := recover()
if r != nil {
tx.Rollback()
}
}()
ctxWithTxn := context.WithValue(ctx, "tx", tx)
res, err := f(ctxWithTxn)
if err != nil {
tx.Rollback()
return nil, err
}
tx.Commit()
return res, nil
}
func (r *Repository) DB(ctx context.Context) *gorm.DB {
// retrieve tx from ctx, if nil -> return r.db
tx, ok := ctx.Value("tx").(*gorm.DB)
if ok {
return tx
}
return r.client.db
}