|
|
|
@ -1,4 +1,4 @@ |
|
|
|
package storage |
|
|
|
package redis |
|
|
|
|
|
|
|
import ( |
|
|
|
"context" |
|
|
|
@ -6,11 +6,15 @@ import ( |
|
|
|
"time" |
|
|
|
|
|
|
|
"github.com/go-redis/redis/v8" |
|
|
|
"gorm.io/gorm" |
|
|
|
|
|
|
|
"github.com/yedf/dtm/common" |
|
|
|
"github.com/yedf/dtm/dtmcli/dtmimp" |
|
|
|
"gorm.io/gorm" |
|
|
|
"github.com/yedf/dtm/dtmsvr/storage" |
|
|
|
) |
|
|
|
|
|
|
|
var config = &common.Config |
|
|
|
|
|
|
|
var ctx context.Context = context.Background() |
|
|
|
|
|
|
|
type RedisStore struct { |
|
|
|
@ -26,30 +30,30 @@ func (s *RedisStore) PopulateData(skipDrop bool) { |
|
|
|
dtmimp.PanicIf(err != nil, err) |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) FindTransGlobalStore(gid string) *TransGlobalStore { |
|
|
|
func (s *RedisStore) FindTransGlobalStore(gid string) *storage.TransGlobalStore { |
|
|
|
r, err := redisGet().Get(ctx, config.Store.RedisPrefix+"_g_"+gid).Result() |
|
|
|
if err == redis.Nil { |
|
|
|
return nil |
|
|
|
} |
|
|
|
dtmimp.E2P(err) |
|
|
|
trans := &TransGlobalStore{} |
|
|
|
trans := &storage.TransGlobalStore{} |
|
|
|
dtmimp.MustUnmarshalString(r, trans) |
|
|
|
return trans |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []TransGlobalStore { |
|
|
|
func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []storage.TransGlobalStore { |
|
|
|
lid := uint64(0) |
|
|
|
if *position != "" { |
|
|
|
lid = uint64(dtmimp.MustAtoi(*position)) |
|
|
|
} |
|
|
|
keys, cursor, err := redisGet().Scan(ctx, lid, config.Store.RedisPrefix+"_g_*", limit).Result() |
|
|
|
dtmimp.E2P(err) |
|
|
|
globals := []TransGlobalStore{} |
|
|
|
globals := []storage.TransGlobalStore{} |
|
|
|
if len(keys) > 0 { |
|
|
|
values, err := redisGet().MGet(ctx, keys...).Result() |
|
|
|
dtmimp.E2P(err) |
|
|
|
for _, v := range values { |
|
|
|
global := TransGlobalStore{} |
|
|
|
global := storage.TransGlobalStore{} |
|
|
|
dtmimp.MustUnmarshalString(v.(string), &global) |
|
|
|
globals = append(globals, global) |
|
|
|
} |
|
|
|
@ -62,17 +66,17 @@ func (s *RedisStore) ScanTransGlobalStores(position *string, limit int64) []Tran |
|
|
|
return globals |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) FindBranches(gid string) []TransBranchStore { |
|
|
|
func (s *RedisStore) FindBranches(gid string) []storage.TransBranchStore { |
|
|
|
sa, err := redisGet().LRange(ctx, config.Store.RedisPrefix+"_b_"+gid, 0, -1).Result() |
|
|
|
dtmimp.E2P(err) |
|
|
|
branches := make([]TransBranchStore, len(sa)) |
|
|
|
branches := make([]storage.TransBranchStore, len(sa)) |
|
|
|
for k, v := range sa { |
|
|
|
dtmimp.MustUnmarshalString(v, &branches[k]) |
|
|
|
} |
|
|
|
return branches |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) UpdateBranchesSql(branches []TransBranchStore, updates []string) *gorm.DB { |
|
|
|
func (s *RedisStore) UpdateBranchesSql(branches []storage.TransBranchStore, updates []string) *gorm.DB { |
|
|
|
return nil // not implemented
|
|
|
|
} |
|
|
|
|
|
|
|
@ -102,7 +106,7 @@ func (a *argList) AppendObject(v interface{}) *argList { |
|
|
|
return a.AppendRaw(dtmimp.MustMarshalString(v)) |
|
|
|
} |
|
|
|
|
|
|
|
func (a *argList) AppendBranches(branches []TransBranchStore) *argList { |
|
|
|
func (a *argList) AppendBranches(branches []storage.TransBranchStore) *argList { |
|
|
|
for _, b := range branches { |
|
|
|
a.AppendRaw(dtmimp.MustMarshalString(b)) |
|
|
|
} |
|
|
|
@ -116,8 +120,8 @@ func handleRedisResult(ret interface{}, err error) (string, error) { |
|
|
|
} |
|
|
|
s, _ := ret.(string) |
|
|
|
err = map[string]error{ |
|
|
|
"NOT_FOUND": ErrNotFound, |
|
|
|
"UNIQUE_CONFLICT": ErrUniqueConflict, |
|
|
|
"NOT_FOUND": storage.ErrNotFound, |
|
|
|
"UNIQUE_CONFLICT": storage.ErrUniqueConflict, |
|
|
|
}[s] |
|
|
|
return s, err |
|
|
|
} |
|
|
|
@ -128,7 +132,7 @@ func callLua(a *argList, lua string) (string, error) { |
|
|
|
return handleRedisResult(ret, err) |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) MaySaveNewTrans(global *TransGlobalStore, branches []TransBranchStore) error { |
|
|
|
func (s *RedisStore) MaySaveNewTrans(global *storage.TransGlobalStore, branches []storage.TransBranchStore) error { |
|
|
|
a := newArgList(). |
|
|
|
AppendGid(global.Gid). |
|
|
|
AppendObject(global). |
|
|
|
@ -153,10 +157,10 @@ redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) LockGlobalSaveBranches(gid string, status string, branches []TransBranchStore, branchStart int) { |
|
|
|
func (s *RedisStore) LockGlobalSaveBranches(gid string, status string, branches []storage.TransBranchStore, branchStart int) { |
|
|
|
args := newArgList(). |
|
|
|
AppendGid(gid). |
|
|
|
AppendObject(&TransGlobalStore{Gid: gid, Status: status}). |
|
|
|
AppendObject(&storage.TransGlobalStore{Gid: gid, Status: status}). |
|
|
|
AppendRaw(branchStart). |
|
|
|
AppendBranches(branches) |
|
|
|
_, err := callLua(args, ` |
|
|
|
@ -182,7 +186,7 @@ redis.call('EXPIRE', KEYS[2], ARGV[2]) |
|
|
|
dtmimp.E2P(err) |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) ChangeGlobalStatus(global *TransGlobalStore, newStatus string, updates []string, finished bool) { |
|
|
|
func (s *RedisStore) ChangeGlobalStatus(global *storage.TransGlobalStore, newStatus string, updates []string, finished bool) { |
|
|
|
old := global.Status |
|
|
|
global.Status = newStatus |
|
|
|
args := newArgList().AppendGid(global.Gid).AppendObject(global).AppendRaw(old).AppendRaw(finished) |
|
|
|
@ -205,7 +209,7 @@ end |
|
|
|
dtmimp.E2P(err) |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) LockOneGlobalTrans(expireIn time.Duration) *TransGlobalStore { |
|
|
|
func (s *RedisStore) LockOneGlobalTrans(expireIn time.Duration) *storage.TransGlobalStore { |
|
|
|
expired := time.Now().Add(expireIn).Unix() |
|
|
|
next := time.Now().Add(time.Duration(config.RetryInterval) * time.Second).Unix() |
|
|
|
args := newArgList().AppendGid("").AppendRaw(expired).AppendRaw(next) |
|
|
|
@ -224,7 +228,7 @@ return gid |
|
|
|
` |
|
|
|
for { |
|
|
|
r, err := callLua(args, lua) |
|
|
|
if err == ErrNotFound { |
|
|
|
if err == storage.ErrNotFound { |
|
|
|
return nil |
|
|
|
} |
|
|
|
dtmimp.E2P(err) |
|
|
|
@ -235,7 +239,7 @@ return gid |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (s *RedisStore) TouchCronTime(global *TransGlobalStore, nextCronInterval int64) { |
|
|
|
func (s *RedisStore) TouchCronTime(global *storage.TransGlobalStore, nextCronInterval int64) { |
|
|
|
global.NextCronTime = common.GetNextTime(nextCronInterval) |
|
|
|
global.UpdateTime = common.GetNextTime(0) |
|
|
|
global.NextCronInterval = nextCronInterval |
|
|
|
@ -255,3 +259,7 @@ redis.call('SET', KEYS[1], ARGV[3], 'EX', ARGV[2]) |
|
|
|
`) |
|
|
|
dtmimp.E2P(err) |
|
|
|
} |
|
|
|
|
|
|
|
func redisGet() *redis.Client { |
|
|
|
return common.RedisGet() |
|
|
|
} |