/
transaction.go
80 lines (64 loc) · 2.02 KB
/
transaction.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
78
79
80
package db
import "context"
var (
transactionContextKey = "transactionContextKey"
nonTransactionalContextKey = "nonTransactionalContextKey"
)
// NewContextWithTransaction stores transaction and original context into a transactional context
func NewContextWithTransaction(ctx context.Context, tx interface{}) context.Context {
ctx = context.WithValue(ctx, &nonTransactionalContextKey, ctx)
return context.WithValue(ctx, &transactionContextKey, tx)
}
// GetTransaction returns original transaction object
func GetTransaction(ctx context.Context) interface{} {
return ctx.Value(&transactionContextKey)
}
// GetNonTransactionalContext returns non transaction context (e.g. parent of transactional context)
// TODO: This is can be dangerous if child context creates a new context with a deadline for example
func GetNonTransactionalContext(ctx context.Context) context.Context {
return ctx.Value(&nonTransactionalContextKey).(context.Context)
}
type TransactionOptions interface {
IsReadonly() bool
IsCrossGroup() bool
Password() string
}
type TransactionOption func(options *transactionOptions)
type transactionOptions struct {
isReadonly bool
isCrossGroup bool
password string
}
var _ TransactionOptions = (*transactionOptions)(nil)
func (v transactionOptions) IsReadonly() bool {
return v.isReadonly
}
func (v transactionOptions) IsCrossGroup() bool {
return v.isCrossGroup
}
// Password // TODO: why we need it?
func (v transactionOptions) Password() string {
return v.password
}
func NewTransactionOptions(opts ...TransactionOption) TransactionOptions {
options := transactionOptions{}
for _, opt := range opts {
opt(&options)
}
return options
}
func WithReadonly() TransactionOption {
return func(options *transactionOptions) {
options.isReadonly = true
}
}
func WithCrossGroup() TransactionOption {
return func(options *transactionOptions) {
options.isCrossGroup = true
}
}
func WithPassword(password string) TransactionOption {
return func(options *transactionOptions) {
options.password = password
}
}