Skip to content

Commit

Permalink
Merge pull request #40 from suyuan32/mg
Browse files Browse the repository at this point in the history
Merge latest codes
  • Loading branch information
suyuan32 authored Apr 3, 2023
2 parents f5aeb10 + 3bc3f84 commit b886083
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 131 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,17 @@ jobs:
- name: Lint
run: |
go vet -stdmethods=false $(go list ./...)
go install mvdan.cc/gofumpt@latest
test -z "$(gofumpt -l -extra .)" || echo "Please run 'gofumpt -l -w -extra .'"
if ! test -z "$(gofmt -l .)"; then
echo "Please run 'gofmt -l -w .'"
exit 1
fi
go mod tidy
if ! test -z "$(git status --porcelain)"; then
echo "Please run 'go mod tidy'"
exit 1
fi
- name: Test
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
Expand Down
22 changes: 12 additions & 10 deletions core/bloom/bloom.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,27 @@ import (
const (
// for detailed error rate table, see http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html
// maps as k in the error rate table
maps = 14
setScript = `
maps = 14
)

var (
// ErrTooLargeOffset indicates the offset is too large in bitset.
ErrTooLargeOffset = errors.New("too large offset")
setScript = redis.NewScript(`
for _, offset in ipairs(ARGV) do
redis.call("setbit", KEYS[1], offset, 1)
end
`
testScript = `
`)
testScript = redis.NewScript(`
for _, offset in ipairs(ARGV) do
if tonumber(redis.call("getbit", KEYS[1], offset)) == 0 then
return false
end
end
return true
`
`)
)

// ErrTooLargeOffset indicates the offset is too large in bitset.
var ErrTooLargeOffset = errors.New("too large offset")

type (
// A Filter is a bloom filter.
Filter struct {
Expand Down Expand Up @@ -117,7 +119,7 @@ func (r *redisBitSet) check(offsets []uint) (bool, error) {
return false, err
}

resp, err := r.store.Eval(testScript, []string{r.key}, args)
resp, err := r.store.ScriptRun(testScript, []string{r.key}, args)
if err == redis.Nil {
return false, nil
} else if err != nil {
Expand Down Expand Up @@ -147,7 +149,7 @@ func (r *redisBitSet) set(offsets []uint) error {
return err
}

_, err = r.store.Eval(setScript, []string{r.key}, args)
_, err = r.store.ScriptRun(setScript, []string{r.key}, args)
if err == redis.Nil {
return nil
}
Expand Down
55 changes: 49 additions & 6 deletions core/bloom/bloom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis/redistest"
)

func TestRedisBitSet_New_Set_Test(t *testing.T) {
store, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
store := redistest.CreateRedis(t)

bitSet := newRedisBitSet(store, "test_key", 1024)
isSetBefore, err := bitSet.check([]uint{0})
Expand Down Expand Up @@ -42,9 +41,7 @@ func TestRedisBitSet_New_Set_Test(t *testing.T) {
}

func TestRedisBitSet_Add(t *testing.T) {
store, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
store := redistest.CreateRedis(t)

filter := New(store, "test_key", 64)
assert.Nil(t, filter.Add([]byte("hello")))
Expand All @@ -53,3 +50,49 @@ func TestRedisBitSet_Add(t *testing.T) {
assert.Nil(t, err)
assert.True(t, ok)
}

func TestFilter_Exists(t *testing.T) {
store, clean := redistest.CreateRedisWithClean(t)

rbs := New(store, "test", 64)
_, err := rbs.Exists([]byte{0, 1, 2})
assert.NoError(t, err)

clean()
rbs = New(store, "test", 64)
_, err = rbs.Exists([]byte{0, 1, 2})
assert.Error(t, err)
}

func TestRedisBitSet_check(t *testing.T) {
store, clean := redistest.CreateRedisWithClean(t)

rbs := newRedisBitSet(store, "test", 0)
assert.Error(t, rbs.set([]uint{0, 1, 2}))
_, err := rbs.check([]uint{0, 1, 2})
assert.Error(t, err)

rbs = newRedisBitSet(store, "test", 64)
_, err = rbs.check([]uint{0, 1, 2})
assert.NoError(t, err)

clean()
rbs = newRedisBitSet(store, "test", 64)
_, err = rbs.check([]uint{0, 1, 2})
assert.Error(t, err)
}

func TestRedisBitSet_set(t *testing.T) {
logx.Disable()
store, clean := redistest.CreateRedisWithClean(t)

rbs := newRedisBitSet(store, "test", 0)
assert.Error(t, rbs.set([]uint{0, 1, 2}))

rbs = newRedisBitSet(store, "test", 64)
assert.NoError(t, rbs.set([]uint{0, 1, 2}))

clean()
rbs = newRedisBitSet(store, "test", 64)
assert.Error(t, rbs.set([]uint{0, 1, 2}))
}
38 changes: 20 additions & 18 deletions core/limit/periodlimit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@ import (
"github.com/zeromicro/go-zero/core/stores/redis"
)

// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
const periodScript = `local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call("INCRBY", KEYS[1], 1)
if current == 1 then
redis.call("expire", KEYS[1], window)
end
if current < limit then
return 1
elseif current == limit then
return 2
else
return 0
end`

const (
// Unknown means not initialized state.
Unknown = iota
Expand All @@ -39,8 +24,25 @@ const (
internalHitQuota = 2
)

// ErrUnknownCode is an error that represents unknown status code.
var ErrUnknownCode = errors.New("unknown status code")
var (
// ErrUnknownCode is an error that represents unknown status code.
ErrUnknownCode = errors.New("unknown status code")

// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
periodScript = redis.NewScript(`local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call("INCRBY", KEYS[1], 1)
if current == 1 then
redis.call("expire", KEYS[1], window)
end
if current < limit then
return 1
elseif current == limit then
return 2
else
return 0
end`)
)

type (
// PeriodOption defines the method to customize a PeriodLimit.
Expand Down Expand Up @@ -80,7 +82,7 @@ func (h *PeriodLimit) Take(key string) (int, error) {

// TakeCtx requests a permit with context, it returns the permit state.
func (h *PeriodLimit) TakeCtx(ctx context.Context, key string) (int, error) {
resp, err := h.limitStore.EvalCtx(ctx, periodScript, []string{h.keyPrefix + key}, []string{
resp, err := h.limitStore.ScriptRunCtx(ctx, periodScript, []string{h.keyPrefix + key}, []string{
strconv.Itoa(h.quota),
strconv.Itoa(h.calcExpireSeconds()),
})
Expand Down
4 changes: 1 addition & 3 deletions core/limit/periodlimit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ func TestPeriodLimit_RedisUnavailable(t *testing.T) {
}

func testPeriodLimit(t *testing.T, opts ...PeriodOption) {
store, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
store := redistest.CreateRedis(t)

const (
seconds = 1
Expand Down
21 changes: 11 additions & 10 deletions core/limit/tokenlimit.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ import (
)

const (
// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
// KEYS[1] as tokens_key
// KEYS[2] as timestamp_key
script = `local rate = tonumber(ARGV[1])
tokenFormat = "{%s}.tokens"
timestampFormat = "{%s}.ts"
pingInterval = time.Millisecond * 100
)

// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
// KEYS[1] as tokens_key
// KEYS[2] as timestamp_key
var script = redis.NewScript(`local rate = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])
Expand All @@ -45,11 +50,7 @@ end
redis.call("setex", KEYS[1], ttl, new_tokens)
redis.call("setex", KEYS[2], ttl, now)
return allowed`
tokenFormat = "{%s}.tokens"
timestampFormat = "{%s}.ts"
pingInterval = time.Millisecond * 100
)
return allowed`)

// A TokenLimiter controls how frequently events are allowed to happen with in one second.
type TokenLimiter struct {
Expand Down Expand Up @@ -110,7 +111,7 @@ func (lim *TokenLimiter) reserveN(ctx context.Context, now time.Time, n int) boo
return lim.rescueLimiter.AllowN(now, n)
}

resp, err := lim.store.EvalCtx(ctx,
resp, err := lim.store.ScriptRunCtx(ctx,
script,
[]string{
lim.tokenKey,
Expand Down
8 changes: 2 additions & 6 deletions core/limit/tokenlimit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ func TestTokenLimit_Rescue(t *testing.T) {
}

func TestTokenLimit_Take(t *testing.T) {
store, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
store := redistest.CreateRedis(t)

const (
total = 100
Expand All @@ -92,9 +90,7 @@ func TestTokenLimit_Take(t *testing.T) {
}

func TestTokenLimit_TakeBurst(t *testing.T) {
store, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
store := redistest.CreateRedis(t)

const (
total = 100
Expand Down
12 changes: 3 additions & 9 deletions core/stores/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,8 @@ func (mc *mockedNode) TakeWithExpireCtx(ctx context.Context, val any, key string
func TestCache_SetDel(t *testing.T) {
t.Run("test set del", func(t *testing.T) {
const total = 1000
r1, clean1, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean1()
r2, clean2, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean2()
r1 := redistest.CreateRedis(t)
r2 := redistest.CreateRedis(t)
conf := ClusterConf{
{
RedisConf: redis.RedisConf{
Expand Down Expand Up @@ -193,9 +189,7 @@ func TestCache_SetDel(t *testing.T) {

func TestCache_OneNode(t *testing.T) {
const total = 1000
r, clean, err := redistest.CreateRedis()
assert.Nil(t, err)
defer clean()
r := redistest.CreateRedis(t)
conf := ClusterConf{
{
RedisConf: redis.RedisConf{
Expand Down
Loading

0 comments on commit b886083

Please sign in to comment.