Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"monitor_test.go",
"net_test.go",
"task_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cluster.go",
"dao.go",
"monitor.go",
"net.go",
"task.go",
],
importpath = "go-common/app/admin/main/aegis/dao/redis",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/monitor:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//library/cache/redis:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,243 @@
package redis
import (
"context"
"encoding/json"
"fmt"
"time"
modtask "go-common/app/admin/main/aegis/model/task"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
"github.com/pkg/errors"
)
func lockKey(businessID, flowID int64) string {
return fmt.Sprintf("aegis_lock_%d_%d", businessID, flowID)
}
func (d *Dao) getlock(c context.Context, bizid, flowid int64) (ok bool) {
var (
conn = d.cluster.Get(c)
key = lockKey(bizid, flowid)
err error
)
defer conn.Close()
if ok, err = redis.Bool(conn.Do("SETNX", key, "1")); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(SETNX(%s)) error(%v)", key, err)
return
}
}
if ok {
conn.Do("EXPIRE", key, 3)
}
return
}
//SeizeTask .
func (d *Dao) SeizeTask(c context.Context, businessID, flowID, uid, count int64) (hitids []int64, missids []int64, others map[int64]int64, err error) {
var (
lock bool
pubkey = publicKey(businessID, flowID)
ids []int64
)
// 1. 抢占分布式锁
for lc := 0; lc < 3; lc++ {
if lock = d.getlock(c, businessID, flowID); lock {
break
}
time.Sleep(10 * time.Millisecond)
}
if !lock {
log.Error("getlock getlock fail(%d,%d,%d)", businessID, flowID, uid)
err = ecode.AegisTaskBusy
return
}
conn := d.cluster.Get(c)
defer conn.Close()
defer conn.Do("DEL", lockKey(businessID, flowID))
var (
head, tail = int64(0), int64(count)
)
// 2. 从 public 按权重从高到低取出一批来
for {
if ids, err = redis.Int64s(conn.Do("ZRANGE", pubkey, head, tail)); err != nil {
log.Error("redis (ZRANGE,%s,%d,%d) error(%v)", pubkey, 0, count, err)
return
}
head += count
tail += count
if len(ids) == 0 {
break
}
for _, id := range ids {
if err = conn.Send("GET", haskKey(id)); err != nil {
log.Error("redis (GET,%s) error(%v)", haskKey(id), err)
return
}
}
conn.Flush()
var enough bool
for _, id := range ids {
var (
bs []byte
e error
)
bs, e = redis.Bytes(conn.Receive())
if e != nil {
log.Error("Receive Weight(%d) error(%v)", id, errors.WithStack(e))
missids = append(missids, id)
continue
}
task := &modtask.Task{}
if e = json.Unmarshal(bs, task); err != nil {
log.Error("json.Unmarshal error(%v)", errors.WithStack(e))
missids = append(missids, id)
continue
}
if task.ID != id {
log.Error("id(%d-%d)不匹配", task.ID, id)
missids = append(missids, id)
continue
}
if task.UID != 0 && task.UID != uid {
log.Info("id(%d) 任务已经指派给(%d)", task.ID, task.UID)
missids = append(missids, id)
continue
}
hitids = append(hitids, id)
if len(hitids) >= int(count) {
enough = true
break
}
}
if enough {
break
}
}
personKey := personalKey(businessID, flowID, uid)
for _, id := range hitids {
conn.Send("ZREM", pubkey, formatID(id))
conn.Send("LREM", personKey, 0, id)
conn.Send("RPUSH", personKey, id)
}
conn.Flush()
for i := 0; i < len(hitids)*3; i++ {
conn.Receive()
}
log.Info("rangefunc count(%d) hitids(%v) missids(%v)", count, hitids, missids)
return
}
/*
遍历personal,delay,public。
在缓存中进行状态校验public还要补充缓存权重
*/
func (d *Dao) rangefuncCluster(c context.Context, listtype string, opt *modtask.ListOptions) (tasks map[int64]*modtask.Task, count int64, hitids, missids []int64, err error) {
var (
key string
LENCMD, RANGECMD = "LLEN", "LRANGE"
ids []int64
)
conn := d.cluster.Get(c)
defer conn.Close()
switch listtype {
case "public":
LENCMD, RANGECMD = "ZCARD", "ZRANGE"
key = publicKey(opt.BusinessID, opt.FlowID)
case "personal":
key = personalKey(opt.BusinessID, opt.FlowID, opt.UID)
case "delay":
key = delayKey(opt.BusinessID, opt.FlowID, opt.UID)
}
// 1. 长度
if count, err = redis.Int64(conn.Do(LENCMD, key)); err != nil {
log.Error("redis (%s,%s) error(%v)", LENCMD, key, err)
return
}
if count == 0 {
return
}
if ids, err = redis.Int64s(conn.Do(RANGECMD, key, (opt.Pn-1)*opt.Ps, opt.Pn*opt.Ps-1)); err != nil {
log.Error("redis (%s,%s,%d,%d) error(%v)", LENCMD, key, (opt.Pn-1)*opt.Ps, opt.Pn*opt.Ps, err)
return
}
for _, id := range ids {
if err = conn.Send("GET", haskKey(id)); err != nil {
log.Error("redis (GET,%s) error(%v)", haskKey(id), err)
return
}
if listtype == "public" {
if err = conn.Send("ZSCORE", key, formatID(id)); err != nil {
log.Error("redis (ZSCORE,%s,%s) error(%v)", key, formatID(id), err)
return
}
}
}
conn.Flush()
tasks = make(map[int64]*modtask.Task)
for _, id := range ids {
var (
bs []byte
e error
wt int64
)
bs, e = redis.Bytes(conn.Receive())
if listtype == "public" {
wt, _ = redis.Int64(conn.Receive())
wt = -wt
}
if e != nil {
log.Error("Receive Weight(%d) error(%v)", id, errors.WithStack(e))
missids = append(missids, id)
continue
}
task := &modtask.Task{}
if e = json.Unmarshal(bs, task); err != nil {
log.Error("json.Unmarshal error(%v)", errors.WithStack(e))
missids = append(missids, id)
continue
}
if task.ID != id {
log.Error("id(%d-%d)不匹配", task.ID, id)
missids = append(missids, id)
continue
}
// 缓存里状态同步不实时,不能用作校验
tasks[task.ID] = task
hitids = append(hitids, id)
}
log.Info("rangefunc count(%d) hitids(%v) missids(%v)", count, hitids, missids)
return
}

View File

@@ -0,0 +1,39 @@
package redis
import (
"context"
"go-common/app/admin/main/aegis/conf"
"go-common/library/cache/redis"
)
// Dao dao
type Dao struct {
c *conf.Config
cluster *redis.Pool
netExpire int64
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
cluster: redis.NewPool(c.Redis.Cluster),
netExpire: int64(c.Redis.NetExpire),
}
if dao.netExpire == 0 {
dao.netExpire = int64(1800) //30m
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.cluster.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}

View File

@@ -0,0 +1,52 @@
package redis
import (
"context"
"flag"
"fmt"
"os"
"testing"
"go-common/app/admin/main/aegis/conf"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
cntx context.Context
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.aegis-admin")
flag.Set("conf_token", "cad913269be022e1eb8c45a8d5408d78")
flag.Set("tree_id", "60977")
flag.Set("conf_version", "1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/aegis-admin.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(fmt.Sprintf("conf.Init() error(%v)", err))
}
d = New(conf.Conf)
cntx = context.TODO()
os.Exit(m.Run())
}
func TestRedisPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.Ping(cntx)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,65 @@
package redis
import (
"context"
"fmt"
"go-common/app/admin/main/aegis/model/monitor"
"go-common/library/cache/redis"
"go-common/library/log"
"strconv"
"time"
)
// MoniRuleStats 获取监控统计
func (d *Dao) MoniRuleStats(c context.Context, id, min, max int64) (stats *monitor.Stats, err error) {
var (
conn = d.cluster.Get(c)
key = fmt.Sprintf(monitor.RedisPrefix, id)
now = time.Now().Unix()
)
stats = &monitor.Stats{}
defer conn.Close()
if stats.TotalCount, err = redis.Int(conn.Do("ZCOUNT", key, 0, now)); err != nil {
log.Error("conn.Do(ZCOUNT,%s,0,%d) error(%v)", key, now, err)
return
}
if stats.MoniCount, err = redis.Int(conn.Do("ZCOUNT", key, min, max)); err != nil {
log.Error("conn.Do(ZCOUNT,%s,%d,%d) error(%v)", key, min, max, err)
return
}
var oldest map[string]string //进入列表最久的项
oldest, err = redis.StringMap(conn.Do("ZRANGE", key, 0, 0, "WITHSCORES"))
for _, t := range oldest {
var i int
if i, err = strconv.Atoi(t); err != nil {
return
}
stats.MaxTime = int(now) - i
}
return
}
// MoniRuleOids 获取监控符合报警时长的
func (d *Dao) MoniRuleOids(c context.Context, id, min, max int64) (oidMap map[int64]int, err error) {
var (
key = fmt.Sprintf(monitor.RedisPrefix, id)
conn = d.cluster.Get(c)
strMap map[string]int
)
oidMap = make(map[int64]int)
strMap = make(map[string]int)
defer conn.Close()
if strMap, err = redis.IntMap(conn.Do("ZRANGEBYSCORE", key, min, max, "WITHSCORES")); err != nil {
log.Error("redis.IntMap(conn.Do(\"ZRANGEBYSCORE\", %s, %d, %d, \"WITHSCORES\")) error(%v)", key, min, max, err)
return
}
for k, v := range strMap {
oid := 0
if oid, err = strconv.Atoi(k); err != nil {
log.Error("strconv.Atoi(%s) error(%v)", k, err)
}
oidMap[int64(oid)] = v
}
return
}

View File

@@ -0,0 +1,31 @@
package redis
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestRedisMoniRuleStats(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("MoniRuleStats", t, func(ctx convey.C) {
_, err := d.MoniRuleStats(c, 1, 0, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestRedisMoniRuleOids(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("MoniRuleOids", t, func(ctx convey.C) {
_, err := d.MoniRuleOids(c, 1, 0, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,71 @@
package redis
import (
"context"
"go-common/library/cache/redis"
"go-common/library/log"
)
//SetMulti setex key expire val, kvs as multi key val
func (d *Dao) SetMulti(c context.Context, kvs map[string]string) (err error) {
if len(kvs) == 0 {
return
}
conn := d.cluster.Get(c)
defer conn.Close()
//拼接参数
for key, val := range kvs {
if err = conn.Send("SETEX", key, d.netExpire, val); err != nil {
log.Error("SetMulti conn.send(SETEX) error(%v)", err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("SetMulti conn.Flush error(%v)", err)
}
return
}
//MGet get multi key value
func (d *Dao) MGet(c context.Context, keys ...string) (dest []string, err error) {
//检测参数
if len(keys) == 0 {
return
}
//拼接查询参数+ redis请求
args := redis.Args{}
for _, item := range keys {
args = args.Add(item)
}
conn := d.cluster.Get(c)
defer conn.Close()
if dest, err = redis.Strings(conn.Do("MGET", args...)); err != nil {
log.Error("MGet conn.Do(mget) error(%v) args(%+v)", err, args)
}
return
}
//DelMulti del redis keys
func (d *Dao) DelMulti(c context.Context, keys ...string) (err error) {
if len(keys) == 0 {
return
}
conn := d.cluster.Get(c)
defer conn.Close()
args := redis.Args{}
for _, k := range keys {
args = args.Add(k)
}
if _, err = redis.Int(conn.Do("DEL", args...)); err != nil {
log.Error("DelMulti conn.Do(del) error(%v) args(%+v)", err, args)
}
return
}

View File

@@ -0,0 +1,53 @@
package redis
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var (
kvs = map[string]string{
"test:1": "test111-11",
"test:2": "test222-22",
}
ks = []string{"test:1", "test:2"}
)
func TestRedisSetMulti(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("SetMulti", t, func(ctx convey.C) {
err := d.SetMulti(c, kvs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestRedisMGet(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("MGet", t, func(ctx convey.C) {
dest, err := d.MGet(c, ks...)
ctx.Convey("Then err should be nil.dest should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(dest, convey.ShouldNotBeNil)
})
})
}
func TestRedisDelMulti(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("DelMulti", t, func(ctx convey.C) {
err := d.DelMulti(c, ks...)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,303 @@
package redis
import (
"context"
"encoding/json"
"fmt"
"time"
"go-common/app/admin/main/aegis/model/common"
modtask "go-common/app/admin/main/aegis/model/task"
"go-common/library/cache/redis"
"go-common/library/log"
"github.com/pkg/errors"
)
/*
四个缓存
1. personalPool 存储每个用户的任务池 类型为List []taskid
2. publicPool 存储还未被领取的任务 类型为Sorted Set weight-taskid
3. delayPool 存储每个用户的延迟任务 类型为List
4. hashTask 存储所有任务的所有其他字段信息
*/
const (
_hashexpire = 24 * 60 * 60
)
func personalKey(businessID, flowID int64, uid int64) string {
return fmt.Sprintf("personal_%d_%d_%d", businessID, flowID, uid)
}
func publicKey(businessID, flowID int64) string {
return fmt.Sprintf("{%d-%d}public_%d_%d", businessID, flowID, businessID, flowID)
}
func delayKey(businessID, flowID int64, uid int64) string {
return fmt.Sprintf("delay_%d_%d_%d", businessID, flowID, uid)
}
func haskKey(taskid int64) string {
return fmt.Sprintf("task_%d", taskid)
}
// formatID 在sorted set里面id要扩展出来否则排序不对
func formatID(taskid int64) string {
return fmt.Sprintf("%.11d", taskid)
}
// CountPersonalTask 统计个数
func (d *Dao) CountPersonalTask(c context.Context, opt *common.BaseOptions) (count int64, err error) {
conn := d.cluster.Get(c)
defer conn.Close()
key := personalKey(opt.BusinessID, opt.FlowID, opt.UID)
if count, err = redis.Int64(conn.Do("LLEN", key)); err != nil {
log.Error("conn.Do(LLEN,%s) error(%v)", key, err)
}
return
}
// RangePersonalTask 从本人的任务池取
func (d *Dao) RangePersonalTask(c context.Context, opt *modtask.ListOptions) (tasks map[int64]*modtask.Task, count int64, hitids, missids []int64, err error) {
tasks, count, hitids, missids, err = d.rangefuncCluster(c, "personal", opt)
return
}
// RangeDealyTask .
func (d *Dao) RangeDealyTask(c context.Context, opt *modtask.ListOptions) (tasks map[int64]*modtask.Task, count int64, hitids, missids []int64, err error) {
return d.rangefuncCluster(c, "delay", opt)
}
// RangePublicTask .
func (d *Dao) RangePublicTask(c context.Context, opt *modtask.ListOptions) (tasks map[int64]*modtask.Task, count int64, hitids, missids []int64, err error) {
return d.rangefuncCluster(c, "public", opt)
}
// PushPersonalTask 放入本人任务池
func (d *Dao) PushPersonalTask(c context.Context, opt *common.BaseOptions, ids ...interface{}) (err error) {
key := personalKey(opt.BusinessID, opt.FlowID, opt.UID)
return d.pushList(c, key, ids...)
}
// RemovePersonalTask 任务延迟或完成
func (d *Dao) RemovePersonalTask(c context.Context, opt *common.BaseOptions, ids ...interface{}) (err error) {
key := personalKey(opt.BusinessID, opt.FlowID, opt.UID)
return d.removeList(c, key, ids...)
}
// RemoveDelayTask 延迟任务完成
func (d *Dao) RemoveDelayTask(c context.Context, opt *common.BaseOptions, ids ...interface{}) (err error) {
key := delayKey(opt.BusinessID, opt.FlowID, opt.UID)
return d.removeList(c, key, ids...)
}
func (d *Dao) removeList(c context.Context, key string, ids ...interface{}) (err error) {
conn := d.cluster.Get(c)
defer conn.Close()
for _, id := range ids {
if err = conn.Send("LREM", key, 1, id); err != nil {
log.Error("LREM error(%v)", errors.WithStack(err))
continue
}
}
if err = conn.Flush(); err != nil {
log.Error("Flush error(%v)", errors.WithStack(err))
return
}
for i := 0; i < len(ids); i++ {
if _, err = conn.Receive(); err != nil {
log.Error("Receive error(%v)", errors.WithStack(err))
return
}
}
return
}
// Release 清空个人任务 直接删除key
func (d *Dao) Release(c context.Context, opt *common.BaseOptions, delay bool) (err error) {
var conn = d.cluster.Get(c)
defer conn.Close()
key := personalKey(opt.BusinessID, opt.FlowID, opt.UID)
log.Info("Redis Release(%+v) delay(%v)", opt, delay)
if delay {
debug := func(msg string) {
tasks, count, hitids, missids, err1 := d.rangefuncCluster(c, "personal", &modtask.ListOptions{
BaseOptions: *opt,
Pager: common.Pager{
Pn: 1,
Ps: 10,
},
})
for id, task := range tasks {
log.Info(msg+" Release task(%d)(%+v)", id, task)
}
log.Info(msg+" Release count(%d)", count)
log.Info(msg+" Release hitids(%+v)", hitids)
log.Info(msg+" Release missids(%+v)", missids)
log.Info(msg+" Release err(%+v)", err1)
}
debug("Before")
if _, err = conn.Do("LTRIM", key, 0, 0); err != nil {
log.Error("LTRIM ReleasePersonalTask(%s), error(%v)", key, err)
}
debug("Middle")
time.AfterFunc(5*time.Minute, func() {
d.Release(context.Background(), opt, false)
})
debug("After")
} else {
log.Info("Redis DEL Release(%+v) delay(%v)", opt, delay)
if _, err = conn.Do("DEL", key); err != nil {
log.Error("DEL ReleasePersonalTask(%s), error(%v)", key, err)
}
}
return
}
// PushDelayTask 延迟任务队列
func (d *Dao) PushDelayTask(c context.Context, opt *common.BaseOptions, ids ...interface{}) (err error) {
key := delayKey(opt.BusinessID, opt.FlowID, opt.UID)
return d.pushList(c, key, ids...)
}
func (d *Dao) pushList(c context.Context, key string, values ...interface{}) (err error) {
var (
conn = d.cluster.Get(c)
)
defer conn.Close()
for _, id := range values {
if _, err = conn.Do("LREM", key, 0, id); err != nil {
log.Error("conn.Do(LREM, %v, %v, %v) error(%v)", key, 0, id, err)
return
}
}
args2 := []interface{}{key}
args2 = append(args2, values...)
if _, err = conn.Do("RPUSH", args2...); err != nil {
log.Error("conn.Do(RPUSH, %v) error(%v)", args2, err)
return
}
return
}
// RemovePublicTask 移除
func (d *Dao) RemovePublicTask(c context.Context, opt *common.BaseOptions, ids ...interface{}) (err error) {
conn := d.cluster.Get(c)
defer conn.Close()
key := publicKey(opt.BusinessID, opt.FlowID)
args := []interface{}{key}
nids := []interface{}{}
for _, id := range ids {
nids = append(nids, fmt.Sprintf("%.11d", id))
}
args = append(args, nids...)
if _, err = conn.Do("ZREM", args...); err != nil {
log.Error("(ZREM,%v) error(%v)", args, errors.WithStack(err))
}
return err
}
// PopPublicTask 从实时任务池取出来
func (d *Dao) PopPublicTask(c context.Context, businessID, flowID, count int64) (ids []int64, err error) {
conn := d.cluster.Get(c)
defer conn.Close()
key := publicKey(businessID, flowID)
var tempids []int64
if tempids, err = redis.Int64s(conn.Do("ZRANGE", key, 0, count)); err != nil {
log.Error("conn.Do(ZADD,%s) error(%v)", key, errors.WithStack(err))
}
ids = append(ids, tempids...)
return
}
// PushPublicTask 放入实时任务池
func (d *Dao) PushPublicTask(c context.Context, tasks ...*modtask.Task) (err error) {
conn := d.cluster.Get(c)
defer conn.Close()
for _, task := range tasks {
key := publicKey(task.BusinessID, task.FlowID)
id := formatID(task.ID)
fmt.Println("id:", id)
if _, err = conn.Do("ZADD", key, -task.Weight, id); err != nil {
log.Error("conn.Do(ZADD,%s) error(%v)", key, errors.WithStack(err))
}
}
return
}
// SetTask .
func (d *Dao) SetTask(c context.Context, tasks ...*modtask.Task) (err error) {
conn := d.cluster.Get(c)
defer conn.Close()
for _, task := range tasks {
var bs []byte
key := haskKey(task.ID)
if bs, err = json.Marshal(task); err != nil {
log.Error("json.Marshal(%+v) error(%v)", task, err)
continue
}
if err = conn.Send("SET", key, bs); err != nil {
log.Error("SET error(%v)", err)
continue
}
if err = conn.Send("EXPIRE", key, _hashexpire); err != nil {
log.Error("EXPIRE error(%v)", err)
continue
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < 2*len(tasks); i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}
// GetTask .
func (d *Dao) GetTask(c context.Context, ids []int64) (tasks []*modtask.Task, err error) {
conn := d.cluster.Get(c)
defer conn.Close()
for _, id := range ids {
key := haskKey(id)
conn.Send("GET", key)
}
conn.Flush()
var data []byte
for i := 0; i < len(ids); i++ {
if data, err = redis.Bytes(conn.Receive()); err != nil {
log.Errorv(c, log.KV("event", "redis_get"), log.KV("key", haskKey(ids[i])), log.KV("error", err))
return
}
task := new(modtask.Task)
if err = json.Unmarshal(data, task); err != nil {
log.Errorv(c, log.KV("event", "json.Unmarshal"), log.KV("task", string(data)), log.KV("error", err))
return
}
tasks = append(tasks, task)
}
return
}

View File

@@ -0,0 +1,329 @@
package redis
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/common"
modtask "go-common/app/admin/main/aegis/model/task"
"github.com/smartystreets/goconvey/convey"
)
var (
task1 = &modtask.Task{
ID: 1,
BusinessID: 1,
FlowID: 1,
RID: 1,
Gtime: 0,
Weight: 10,
}
task2 = &modtask.Task{
ID: 2,
BusinessID: 1,
FlowID: 1,
RID: 2,
Gtime: 0,
Weight: 8,
}
task3 = &modtask.Task{
ID: 3,
BusinessID: 1,
FlowID: 1,
RID: 3,
Gtime: 0,
Weight: 8,
}
)
func TestRedisSetTask(t *testing.T) {
convey.Convey("SetTask", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SetTask(c, task1, task2, task3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisPushPublicTask(t *testing.T) {
convey.Convey("PushPublicTask", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.PushPublicTask(c, task1, task2, task3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisRemovePublicTask(t *testing.T) {
convey.Convey("RemovePublicTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.RemovePublicTask(c, opt, 1, 2, 3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisPushPersonalTask(t *testing.T) {
convey.Convey("PushPersonalTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.PushPersonalTask(c, opt, 1, 2, 3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisCountPersonalTask(t *testing.T) {
convey.Convey("CountPersonalTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.CountPersonalTask(c, opt)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisRangePersonalTask(t *testing.T) {
convey.Convey("RangePersonalTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &modtask.ListOptions{
BaseOptions: common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1},
Pager: common.Pager{
Pn: 1,
Ps: 20,
},
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, _, _, err := d.RangePersonalTask(c, opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisRemovePersonalTask(t *testing.T) {
convey.Convey("RemovePersonalTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.RemovePersonalTask(c, opt, 1, 2, 3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisPushDelayTask(t *testing.T) {
convey.Convey("PushDelayTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.PushDelayTask(c, opt, 1, 2, 3)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisRangeDealyTask(t *testing.T) {
convey.Convey("RangeDealyTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &modtask.ListOptions{
BaseOptions: common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1},
Pager: common.Pager{
Pn: 1,
Ps: 20,
},
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tasks, count, hitids, _, err := d.RangeDealyTask(c, opt)
ctx.Convey("Then err should be nil.tasks,count,hitids,missids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(hitids, convey.ShouldNotBeNil)
ctx.So(count, convey.ShouldNotBeNil)
ctx.So(tasks, convey.ShouldNotBeNil)
})
})
})
}
func TestRedisRelease(t *testing.T) {
convey.Convey("Release", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.Release(c, opt, true)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisrangefunc(t *testing.T) {
convey.Convey("rangefunc", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &modtask.ListOptions{
BaseOptions: common.BaseOptions{
BusinessID: 1,
FlowID: 1,
UID: 1},
Pager: common.Pager{
Pn: 1,
Ps: 20,
},
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, _, _, err := d.rangefuncCluster(c, "public", opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisSeize(t *testing.T) {
convey.Convey("SeizeTask", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, _, err := d.SeizeTask(c, 1, 1, 1, 10)
ctx.Convey("Then err should be nil.tasks,count,hitids,missids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisRemoveDelayTask(t *testing.T) {
convey.Convey("RemoveDelayTask", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
ids = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.RemoveDelayTask(c, opt, ids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedispushList(t *testing.T) {
convey.Convey("pushList", t, func(ctx convey.C) {
var (
c = context.Background()
key = ""
values = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.pushList(c, key, values)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisremoveList(t *testing.T) {
convey.Convey("removeList", t, func(ctx convey.C) {
var (
c = context.Background()
key = ""
ids = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.removeList(c, key, ids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestRedisGetTask(t *testing.T) {
convey.Convey("GetTask", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.GetTask(cntx, []int64{1, 2, 3})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}