-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add request time for rpc * change totle time * update * update * update * grpc design docs (#163) * add trace log * change log path * update * sequencer redis (#152) * update * update * [fix] Sequencer redis (#164) fix : for GetSegment method, redis component only check support when size=0. * update * update * update * update * add unittest for runtime and grpc (#169) * update * remove trace time prints * update Co-authored-by: 文徐 <wangwenxue.wwx@alibaba-inc.com> Co-authored-by: 永鹏 <neji_bupt@163.com> Co-authored-by: ZLBer <1098294815@qq.com> Co-authored-by: tianjipeng <tianjipeng@outlook.com>
- Loading branch information
1 parent
f426342
commit e15a60f
Showing
26 changed files
with
2,558 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
components/sequencer/redis/standalone_redis_sequencer.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package redis | ||
|
||
import ( | ||
"context" | ||
"github.com/go-redis/redis/v8" | ||
"mosn.io/layotto/components/pkg/utils" | ||
"mosn.io/layotto/components/sequencer" | ||
"mosn.io/pkg/log" | ||
) | ||
|
||
type StandaloneRedisSequencer struct { | ||
client *redis.Client | ||
metadata utils.RedisMetadata | ||
biggerThan map[string]int64 | ||
|
||
logger log.ErrorLogger | ||
|
||
ctx context.Context | ||
cancel context.CancelFunc | ||
} | ||
|
||
// NewStandaloneRedisSequencer returns a new redis sequencer | ||
func NewStandaloneRedisSequencer(logger log.ErrorLogger) *StandaloneRedisSequencer { | ||
s := &StandaloneRedisSequencer{ | ||
logger: logger, | ||
} | ||
return s | ||
} | ||
|
||
/* | ||
1. exists and >= biggerThan, no operation required, return 0 | ||
2. not exists or < biggthan, reset val, return 1 | ||
3. lua script occur error, such as tonumer(string), return error | ||
*/ | ||
const initScript = ` | ||
if redis.call('exists', KEYS[1])==1 and tonumber(redis.call('get', KEYS[1])) >= tonumber(ARGV[1]) then | ||
return 0 | ||
else | ||
redis.call('set', KEYS[1],ARGV[1]) | ||
return 1 | ||
end | ||
` | ||
|
||
func (s *StandaloneRedisSequencer) Init(config sequencer.Configuration) error { | ||
m, err := utils.ParseRedisMetadata(config.Properties) | ||
if err != nil { | ||
return err | ||
} | ||
//init | ||
s.metadata = m | ||
s.biggerThan = config.BiggerThan | ||
|
||
// construct client | ||
s.client = utils.NewRedisClient(m) | ||
s.ctx, s.cancel = context.WithCancel(context.Background()) | ||
|
||
//check biggerThan, initialize if not satisfied | ||
for k, needV := range s.biggerThan { | ||
if needV <= 0 { | ||
continue | ||
} | ||
|
||
eval := s.client.Eval(s.ctx, initScript, []string{k}, needV) | ||
err = eval.Err() | ||
//occur error, such as value is string type | ||
if err != nil { | ||
return err | ||
} | ||
//As long as there is no error, the initialization is successful | ||
//It may be a reset value or it may be satisfied before | ||
} | ||
return nil | ||
} | ||
|
||
func (s *StandaloneRedisSequencer) GetNextId(req *sequencer.GetNextIdRequest) (*sequencer.GetNextIdResponse, error) { | ||
|
||
incr := s.client.Incr(s.ctx, req.Key) | ||
|
||
err := incr.Err() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &sequencer.GetNextIdResponse{ | ||
NextId: incr.Val(), | ||
}, nil | ||
} | ||
|
||
func (s *StandaloneRedisSequencer) GetSegment(req *sequencer.GetSegmentRequest) (bool, *sequencer.GetSegmentResponse, error) { | ||
|
||
// size=0 only check support | ||
if req.Size == 0 { | ||
return true, nil, nil | ||
} | ||
|
||
by := s.client.IncrBy(s.ctx, req.Key, int64(req.Size)) | ||
err := by.Err() | ||
if err != nil { | ||
return true, nil, err | ||
} | ||
|
||
return true, &sequencer.GetSegmentResponse{ | ||
From: by.Val() - int64(req.Size) + 1, | ||
To: by.Val(), | ||
}, nil | ||
} | ||
func (s *StandaloneRedisSequencer) Close() error { | ||
s.cancel() | ||
return s.client.Close() | ||
} |
136 changes: 136 additions & 0 deletions
136
components/sequencer/redis/standalone_redis_sequencer_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package redis | ||
|
||
import ( | ||
"fmt" | ||
"github.com/alicebob/miniredis/v2" | ||
"github.com/stretchr/testify/assert" | ||
"mosn.io/layotto/components/sequencer" | ||
"mosn.io/pkg/log" | ||
"testing" | ||
) | ||
|
||
const key = "resource_xxx" | ||
|
||
func TestStandaloneRedisSequencer(t *testing.T) { | ||
s, err := miniredis.Run() | ||
assert.NoError(t, err) | ||
defer s.Close() | ||
// construct component | ||
comp := NewStandaloneRedisSequencer(log.DefaultLogger) | ||
cfg := sequencer.Configuration{ | ||
Properties: make(map[string]string), | ||
} | ||
cfg.Properties["redisHost"] = s.Addr() | ||
cfg.Properties["redisPassword"] = "" | ||
// init | ||
err = comp.Init(cfg) | ||
assert.NoError(t, err) | ||
//first request | ||
id, err := comp.GetNextId(&sequencer.GetNextIdRequest{ | ||
Key: key, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, int64(1), id.NextId) | ||
|
||
//again | ||
id, err = comp.GetNextId(&sequencer.GetNextIdRequest{ | ||
Key: key, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, int64(2), id.NextId) | ||
} | ||
|
||
func TestStandaloneRedisSequencer_biggerThan_success(t *testing.T) { | ||
s, err := miniredis.Run() | ||
assert.NoError(t, err) | ||
defer s.Close() | ||
// construct component | ||
comp := NewStandaloneRedisSequencer(log.DefaultLogger) | ||
cfg := sequencer.Configuration{ | ||
Properties: make(map[string]string), | ||
} | ||
defalutVal := int64(20) | ||
//init kv | ||
s.Set(key, fmt.Sprint(defalutVal)) | ||
cfg.Properties["redisHost"] = s.Addr() | ||
cfg.Properties["redisPassword"] = "" | ||
cfg.BiggerThan = map[string]int64{ | ||
key: defalutVal, | ||
} | ||
|
||
// init | ||
err = comp.Init(cfg) | ||
assert.NoError(t, err) | ||
//first request | ||
id, err := comp.GetNextId(&sequencer.GetNextIdRequest{ | ||
Key: key, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, defalutVal+1, id.NextId) | ||
|
||
//again | ||
id, err = comp.GetNextId(&sequencer.GetNextIdRequest{ | ||
Key: key, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, defalutVal+2, id.NextId) | ||
} | ||
|
||
func TestStandaloneRedisSequencer_biggerThan_fail_reset(t *testing.T) { | ||
s, err := miniredis.Run() | ||
assert.NoError(t, err) | ||
defer s.Close() | ||
// construct component | ||
comp := NewStandaloneRedisSequencer(log.DefaultLogger) | ||
cfg := sequencer.Configuration{ | ||
Properties: make(map[string]string), | ||
} | ||
defalutVal := int64(20) | ||
//init kv | ||
s.Set(key, fmt.Sprint(defalutVal)) | ||
// init config | ||
cfg.Properties["redisHost"] = s.Addr() | ||
cfg.Properties["redisPassword"] = "" | ||
cfg.BiggerThan = map[string]int64{ | ||
key: defalutVal + 5, | ||
} | ||
err = comp.Init(cfg) | ||
assert.NoError(t, err) | ||
|
||
//first request | ||
id, err := comp.GetNextId(&sequencer.GetNextIdRequest{ | ||
Key: key, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, defalutVal+5+1, id.NextId) | ||
|
||
} | ||
|
||
func TestStandaloneRedisSequencer_segment(t *testing.T) { | ||
s, err := miniredis.Run() | ||
assert.NoError(t, err) | ||
defer s.Close() | ||
// construct component | ||
comp := NewStandaloneRedisSequencer(log.DefaultLogger) | ||
cfg := sequencer.Configuration{ | ||
Properties: make(map[string]string), | ||
} | ||
defalutVal := int64(20) | ||
//init kv | ||
s.Set(key, fmt.Sprint(defalutVal)) | ||
cfg.Properties["redisHost"] = s.Addr() | ||
cfg.Properties["redisPassword"] = "" | ||
|
||
// init | ||
err = comp.Init(cfg) | ||
assert.NoError(t, err) | ||
//first request | ||
_, id, err := comp.GetSegment(&sequencer.GetSegmentRequest{ | ||
Key: key, | ||
Size: 6, | ||
}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, defalutVal+1, id.From) | ||
assert.Equal(t, defalutVal+6, id.To) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.