-
Notifications
You must be signed in to change notification settings - Fork 182
/
cgi.go
146 lines (127 loc) · 3.66 KB
/
cgi.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package redis_cgi
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"github.com/okex/exchain/libs/tendermint/libs/log"
"github.com/okex/exchain/libs/tendermint/types"
"sync"
"time"
)
const (
lockerExpire = 4 * time.Second
)
var (
mostRecentHeightKey string
deltaLockerKey string
)
var once sync.Once
// init initialize the mostRecentHeightKey and deltaLockerKey
// the keys are based types.DeltaVersion, which can specified by user.
func (r *RedisClient) init() {
const (
mostRecentHeight = "MostRecentHeight"
deltaLocker = "DeltaLocker"
)
once.Do(func() {
mostRecentHeightKey = fmt.Sprintf("dds:%d:%s", types.DeltaVersion, mostRecentHeight)
deltaLockerKey = fmt.Sprintf("dds:%d:%s", types.DeltaVersion, deltaLocker)
})
}
type RedisClient struct {
rdb *redis.Client
ttl time.Duration
logger log.Logger
}
func NewRedisClient(url, auth string, ttl time.Duration, db int, l log.Logger) *RedisClient {
rdb := redis.NewClient(&redis.Options{
Addr: url,
Password: auth, // no password set
DB: db, // use select DB
})
redisClient := RedisClient{rdb, ttl, l}
redisClient.init()
return &redisClient
}
func (r *RedisClient) GetLocker() bool {
res, err := r.rdb.SetNX(context.Background(), deltaLockerKey, true, lockerExpire).Result()
if err != nil {
r.logger.Error("GetLocker err", err)
return false
}
return res
}
func (r *RedisClient) ReleaseLocker() {
_, err := r.rdb.Del(context.Background(), deltaLockerKey).Result()
if err != nil {
r.logger.Error("Failed to Release Locker", "err", err)
}
}
// return bool: if change the value of latest_height, need to upload
func (r *RedisClient) ResetMostRecentHeightAfterUpload(targetHeight int64, upload func(int64) bool) (bool, int64, error) {
var res bool
mrh, err := r.rdb.Get(context.Background(), mostRecentHeightKey).Int64()
if err != nil && err != redis.Nil {
return res, mrh, err
}
if mrh < targetHeight && upload(mrh) {
err = r.rdb.Set(context.Background(), mostRecentHeightKey, targetHeight, 0).Err()
if err == nil {
res = true
r.logger.Info("Reset most recent height", "new-mrh", targetHeight, "old-mrh", mrh)
} else {
r.logger.Error("Failed to reset most recent height",
"target-mrh", targetHeight,
"existing-mrh", mrh, "err", err)
}
}
return res, mrh, err
}
func (r *RedisClient) SetBlock(height int64, bytes []byte) error {
if len(bytes) == 0 {
return fmt.Errorf("block is empty")
}
req := r.rdb.SetNX(context.Background(), genBlockKey(height), bytes, r.ttl)
return req.Err()
}
func (r *RedisClient) SetDeltas(height int64, bytes []byte) error {
if len(bytes) == 0 {
return fmt.Errorf("delta is empty")
}
req := r.rdb.SetNX(context.Background(), genDeltaKey(height), bytes, r.ttl)
return req.Err()
}
func (r *RedisClient) GetBlock(height int64) ([]byte, error) {
bytes, err := r.rdb.Get(context.Background(), genBlockKey(height)).Bytes()
if err == redis.Nil {
return nil, fmt.Errorf("get empty block")
}
if err != nil {
return nil, err
}
return bytes, nil
}
func (r *RedisClient) GetDeltas(height int64) ([]byte, error, int64) {
mrh := r.getMostRecentHeight()
bytes, err := r.rdb.Get(context.Background(), genDeltaKey(height)).Bytes()
if err == redis.Nil {
return nil, fmt.Errorf("get empty delta"), mrh
}
return bytes, err, mrh
}
func (r *RedisClient) getMostRecentHeight() (mrh int64) {
mrh = -1
h, err := r.rdb.Get(context.Background(), mostRecentHeightKey).Int64()
if err == nil {
mrh = h
} else if err == redis.Nil {
mrh = 0
}
return
}
func genBlockKey(height int64) string {
return fmt.Sprintf("BH:%d", height)
}
func genDeltaKey(height int64) string {
return fmt.Sprintf("DH-%d:%d", types.DeltaVersion, height)
}