mirror of https://github.com/dtm-labs/dtm.git
committed by
GitHub
50 changed files with 826 additions and 283 deletions
@ -0,0 +1,14 @@ |
|||
# !/bin/bash |
|||
|
|||
set -x |
|||
|
|||
export LOG_LEVEL=fatal |
|||
export STORE_DRIVER=redis |
|||
export STORE_HOST=localhost |
|||
export STORE_PORT=6379 |
|||
export BUSI_REDIS=localhost:6379 |
|||
./bench redis & |
|||
echo 'sleeping 3s for dtm bench to run up.' && sleep 3 |
|||
curl "http://127.0.0.1:8083/api/busi_bench/benchFlashSalesReset" |
|||
ab -n 300000 -c 20 "http://127.0.0.1:8083/api/busi_bench/benchFlashSales" |
|||
pkill bench |
|||
@ -0,0 +1,73 @@ |
|||
package dtmcli |
|||
|
|||
import ( |
|||
"fmt" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli/logger" |
|||
"github.com/go-redis/redis/v8" |
|||
) |
|||
|
|||
// RedisCheckAdjustAmount check the value of key is valid and >= amount. then adjust the amount
|
|||
func (bb *BranchBarrier) RedisCheckAdjustAmount(rd *redis.Client, key string, amount int, barrierExpire int) error { |
|||
bb.BarrierID = bb.BarrierID + 1 |
|||
bkey1 := fmt.Sprintf("%s-%s-%s-%02d", bb.Gid, bb.BranchID, bb.Op, bb.BarrierID) |
|||
originOp := map[string]string{ |
|||
BranchCancel: BranchTry, |
|||
BranchCompensate: BranchAction, |
|||
}[bb.Op] |
|||
bkey2 := fmt.Sprintf("%s-%s-%s-%02d", bb.Gid, bb.BranchID, originOp, bb.BarrierID) |
|||
v, err := rd.Eval(rd.Context(), ` -- RedisCheckAdjustAmount |
|||
local v = redis.call('GET', KEYS[1]) |
|||
local e1 = redis.call('GET', KEYS[2]) |
|||
|
|||
if v == false or v + ARGV[1] < 0 then |
|||
return 'FAILURE' |
|||
end |
|||
|
|||
if e1 ~= false then |
|||
return |
|||
end |
|||
|
|||
redis.call('SET', KEYS[2], 'op', 'EX', ARGV[3]) |
|||
|
|||
if ARGV[2] ~= '' then |
|||
local e2 = redis.call('GET', KEYS[3]) |
|||
if e2 == false then |
|||
redis.call('SET', KEYS[3], 'rollback', 'EX', ARGV[3]) |
|||
return |
|||
end |
|||
end |
|||
redis.call('INCRBY', KEYS[1], ARGV[1]) |
|||
`, []string{key, bkey1, bkey2}, amount, originOp, barrierExpire).Result() |
|||
logger.Debugf("lua return v: %v err: %v", v, err) |
|||
if err == redis.Nil { |
|||
err = nil |
|||
} |
|||
if err == nil && v == ResultFailure { |
|||
err = ErrFailure |
|||
} |
|||
return err |
|||
} |
|||
|
|||
// RedisQueryPrepared query prepared for redis
|
|||
func (bb *BranchBarrier) RedisQueryPrepared(rd *redis.Client, barrierExpire int) error { |
|||
bkey1 := fmt.Sprintf("%s-%s-%s-%s", bb.Gid, "00", "msg", "01") |
|||
v, err := rd.Eval(rd.Context(), ` -- RedisQueryPrepared |
|||
local v = redis.call('GET', KEYS[1]) |
|||
if v == false then |
|||
redis.call('SET', KEYS[1], 'rollback', 'EX', ARGV[1]) |
|||
v = 'rollback' |
|||
end |
|||
if v == 'rollback' then |
|||
return 'FAILURE' |
|||
end |
|||
`, []string{bkey1}, barrierExpire).Result() |
|||
logger.Debugf("lua return v: %v err: %v", v, err) |
|||
if err == redis.Nil { |
|||
err = nil |
|||
} |
|||
if err == nil && v == ResultFailure { |
|||
err = ErrFailure |
|||
} |
|||
return err |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
package test |
|||
|
|||
import ( |
|||
"errors" |
|||
"testing" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli" |
|||
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
|||
"github.com/dtm-labs/dtm/test/busi" |
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestMsgRedisDo(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenTransReq(30, false, false) |
|||
msg := dtmcli.NewMsg(DtmServer, gid). |
|||
Add(busi.Busi+"/SagaRedisTransIn", req) |
|||
err := msg.DoAndSubmit(Busi+"/RedisQueryPrepared", func(bb *dtmcli.BranchBarrier) error { |
|||
return bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
}) |
|||
assert.Nil(t, err) |
|||
waitTransProcessed(msg.Gid) |
|||
assert.Equal(t, []string{StatusSucceed}, getBranchesStatus(msg.Gid)) |
|||
assert.Equal(t, StatusSucceed, getTransStatus(msg.Gid)) |
|||
assertNotSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgRedisDoBusiFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenTransReq(30, false, false) |
|||
msg := dtmcli.NewMsg(DtmServer, gid). |
|||
Add(busi.Busi+"/SagaRedisTransIn", req) |
|||
err := msg.DoAndSubmit(Busi+"/RedisQueryPrepared", func(bb *dtmcli.BranchBarrier) error { |
|||
return errors.New("an error") |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgRedisDoPrepareFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenTransReq(30, false, false) |
|||
msg := dtmcli.NewMsg(DtmServer+"not-exists", gid). |
|||
Add(busi.Busi+"/SagaRedisTransIn", req) |
|||
err := msg.DoAndSubmit(Busi+"/RedisQueryPrepared", func(bb *dtmcli.BranchBarrier) error { |
|||
return bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgRedisDoCommitFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenTransReq(30, false, false) |
|||
msg := dtmcli.NewMsg(DtmServer, gid). |
|||
Add(busi.Busi+"/SagaRedisTransIn", req) |
|||
err := msg.DoAndSubmit(Busi+"/RedisQueryPrepared", func(bb *dtmcli.BranchBarrier) error { |
|||
return errors.New("after commit error") |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgRedisDoCommitAfterFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenTransReq(30, false, false) |
|||
msg := dtmcli.NewMsg(DtmServer, gid). |
|||
Add(busi.Busi+"/SagaRedisTransIn", req) |
|||
err := msg.DoAndSubmit(Busi+"/RedisQueryPrepared", func(bb *dtmcli.BranchBarrier) error { |
|||
err := bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
dtmimp.E2P(err) |
|||
return errors.New("an error") |
|||
}) |
|||
assert.Error(t, err) |
|||
waitTransProcessed(gid) |
|||
assertNotSameBalance(t, before, "redis") |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
package test |
|||
|
|||
import ( |
|||
"errors" |
|||
"testing" |
|||
|
|||
"github.com/dtm-labs/dtm/dtmcli" |
|||
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
|||
"github.com/dtm-labs/dtm/dtmgrpc" |
|||
"github.com/dtm-labs/dtm/test/busi" |
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestMsgGrpcRedisDo(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenBusiReq(30, false, false) |
|||
msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer, gid). |
|||
Add(busi.BusiGrpc+"/busi.Busi/TransInRedis", req) |
|||
err := msg.DoAndSubmit(busi.BusiGrpc+"/busi.Busi/QueryPreparedRedis", func(bb *dtmcli.BranchBarrier) error { |
|||
return bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
}) |
|||
assert.Nil(t, err) |
|||
waitTransProcessed(msg.Gid) |
|||
assert.Equal(t, []string{StatusSucceed}, getBranchesStatus(msg.Gid)) |
|||
assert.Equal(t, StatusSucceed, getTransStatus(msg.Gid)) |
|||
assertNotSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgGrpcRedisDoBusiFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenBusiReq(30, false, false) |
|||
msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer, gid). |
|||
Add(busi.BusiGrpc+"/busi.Busi/TransInRedis", req) |
|||
err := msg.DoAndSubmit(busi.BusiGrpc+"/busi.Busi/QueryPreparedRedis", func(bb *dtmcli.BranchBarrier) error { |
|||
return errors.New("an error") |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgGrpcRedisDoPrepareFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenBusiReq(30, false, false) |
|||
msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer+"not-exists", gid). |
|||
Add(busi.BusiGrpc+"/busi.Busi/TransInRedis", req) |
|||
err := msg.DoAndSubmit(busi.BusiGrpc+"/busi.Busi/QueryPreparedRedis", func(bb *dtmcli.BranchBarrier) error { |
|||
return bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgGrpcRedisDoCommitFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenBusiReq(30, false, false) |
|||
msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer, gid). |
|||
Add(busi.BusiGrpc+"/busi.Busi/TransInRedis", req) |
|||
err := msg.DoAndSubmit(busi.BusiGrpc+"/busi.Busi/QueryPreparedRedis", func(bb *dtmcli.BranchBarrier) error { |
|||
return errors.New("after commit error") |
|||
}) |
|||
assert.Error(t, err) |
|||
assertSameBalance(t, before, "redis") |
|||
} |
|||
|
|||
func TestMsgGrpcRedisDoCommitAfterFailed(t *testing.T) { |
|||
before := getBeforeBalances("redis") |
|||
gid := dtmimp.GetFuncName() |
|||
req := busi.GenBusiReq(30, false, false) |
|||
msg := dtmgrpc.NewMsgGrpc(DtmGrpcServer, gid). |
|||
Add(busi.BusiGrpc+"/busi.Busi/TransInRedis", req) |
|||
err := msg.DoAndSubmit(busi.BusiGrpc+"/busi.Busi/QueryPreparedRedis", func(bb *dtmcli.BranchBarrier) error { |
|||
err := bb.RedisCheckAdjustAmount(busi.RedisGet(), busi.GetRedisAccountKey(busi.TransOutUID), -30, 86400) |
|||
dtmimp.E2P(err) |
|||
return errors.New("an error") |
|||
}) |
|||
assert.Error(t, err) |
|||
waitTransProcessed(gid) |
|||
assertNotSameBalance(t, before, "redis") |
|||
} |
|||
Loading…
Reference in new issue