Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/aegis/dao/gorm:all-srcs",
"//app/admin/main/aegis/dao/http:all-srcs",
"//app/admin/main/aegis/dao/mc:all-srcs",
"//app/admin/main/aegis/dao/mysql:all-srcs",
"//app/admin/main/aegis/dao/redis:all-srcs",
"//app/admin/main/aegis/dao/rpc:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,89 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"business_config_test.go",
"business_test.go",
"common_test.go",
"dao_test.go",
"direction_test.go",
"flow_resource_test.go",
"flow_test.go",
"net_test.go",
"report_test.go",
"resource_test.go",
"task_config_test.go",
"task_test.go",
"token_test.go",
"transition_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model/business:go_default_library",
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/net:go_default_library",
"//app/admin/main/aegis/model/resource:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"business.go",
"business_config.go",
"common.go",
"dao.go",
"direction.go",
"flow.go",
"flow_resource.go",
"net.go",
"report.go",
"resource.go",
"task.go",
"task_config.go",
"token.go",
"transition.go",
],
importpath = "go-common/app/admin/main/aegis/dao/gorm",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model:go_default_library",
"//app/admin/main/aegis/model/business:go_default_library",
"//app/admin/main/aegis/model/net:go_default_library",
"//app/admin/main/aegis/model/resource:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//library/database/orm:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/jinzhu/gorm: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,66 @@
package gorm
import (
"context"
"go-common/app/admin/main/aegis/model/business"
"github.com/jinzhu/gorm"
)
// AddBusiness .
func (d *Dao) AddBusiness(c context.Context, e *business.Business) (id int64, err error) {
err = d.orm.Table("business").Create(&e).Error
id = e.ID
return
}
// UpdateBusiness .
func (d *Dao) UpdateBusiness(c context.Context, e *business.Business) (err error) {
return d.orm.Table("business").Where("id = ?", e.ID).Update(map[string]interface{}{
"name": e.Name,
"desc": e.Desc,
"developer": e.Developer,
}).Error
}
// EnableBusiness .
func (d *Dao) EnableBusiness(c context.Context, id int64) (err error) {
return d.orm.Table("business").Where("id = ?", id).Update(map[string]interface{}{
"state": business.StateEnable,
}).Error
}
// DisableBusiness .
func (d *Dao) DisableBusiness(c context.Context, id int64) (err error) {
return d.orm.Table("business").Where("id = ?", id).Update(map[string]interface{}{
"state": business.StateDisable,
}).Error
}
// Business .
func (d *Dao) Business(c context.Context, id int64) (res *business.Business, err error) {
res = &business.Business{}
if err = d.orm.Where("id = ?", id).First(&res).Error; err == gorm.ErrRecordNotFound {
res = nil
err = nil
}
return
}
// BusinessList .
func (d *Dao) BusinessList(c context.Context, tp int8, ids []int64, onlyEnable bool) (res []*business.Business, err error) {
res = []*business.Business{}
db := d.orm
if len(ids) > 0 {
db = db.Where("id in (?)", ids)
}
if onlyEnable {
db = db.Where("state=?", business.StateEnable)
}
if tp > 0 {
db = db.Where("type = ?", tp)
}
err = db.Find(&res).Error
return
}

View File

@@ -0,0 +1,68 @@
package gorm
import (
"context"
"database/sql"
"go-common/app/admin/main/aegis/model/business"
"go-common/library/log"
)
// GetConfigs .
func (d *Dao) GetConfigs(c context.Context, bizid int64) (cfgs []*business.BizCFG, err error) {
if err = d.orm.Table("business_config").Where("business_id=? AND state=0", bizid).Scan(&cfgs).Error; err != nil {
log.Error("GetURL error(%v)", err)
}
return
}
// GetConfig .
func (d *Dao) GetConfig(c context.Context, bizid int64, tp int8) (config string, err error) {
if err = d.orm.Table("business_config").Select("`config`").
Where("business_id=? AND type=? AND state=0", bizid, tp).
Order("mtime DESC").Limit(1).
Row().Scan(&config); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("GetConfig error(%v)", err)
return
}
return
}
// ActiveConfigs 所有任务配置
func (d *Dao) ActiveConfigs(c context.Context) (configs []*business.BizCFG, err error) {
configs = []*business.BizCFG{}
if err = d.orm.Where("state=0").Find(&configs).Error; err != nil {
log.Error("ActiveConfigs find error(%v)", err)
}
return
}
// AddBizConfig 每个业务每种配置只有一条
func (d *Dao) AddBizConfig(c context.Context, cfg *business.BizCFG) (lastid int64, err error) {
if err = d.orm.Table("business_config").Where("business_id=? AND `type`=?", cfg.BusinessID, cfg.TP).
Assign(map[string]interface{}{
"config": cfg.Config,
"state": cfg.State,
}).FirstOrCreate(cfg).Error; err != nil {
log.Error("AddBizConfig error(%v)", err)
}
lastid = cfg.ID
return
}
// EditBizConfig .
func (d *Dao) EditBizConfig(c context.Context, cfg *business.BizCFG) (err error) {
if err = d.orm.Table("business_config").Where("id=?", cfg.ID).
Update(map[string]interface{}{
"config": cfg.Config,
"state": cfg.State,
}).Error; err != nil {
log.Error("EditBizConfig error(%v)", err)
}
return
}

View File

@@ -0,0 +1,94 @@
package gorm
import (
"context"
"go-common/app/admin/main/aegis/model/business"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestGormGetConfigs(t *testing.T) {
convey.Convey("GetConfigs", t, func(ctx convey.C) {
var (
c = context.Background()
bizid = int64(1)
)
ctx.Convey("success", func(ctx convey.C) {
cfgs, err := d.GetConfigs(c, bizid)
ctx.Convey("Then err should be nil.cfgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cfgs, convey.ShouldNotBeNil)
})
})
ctx.Convey("empty", func(ctx convey.C) {
_, err := d.GetConfigs(c, -1)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormGetConfig(t *testing.T) {
convey.Convey("GetConfig", t, func(ctx convey.C) {
var (
c = context.Background()
bizid = int64(0)
tp = int8(-1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
config, err := d.GetConfig(c, bizid, tp)
ctx.Convey("Then err should be nil.config should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(config, convey.ShouldNotBeNil)
})
})
})
}
func TestGormActiveConfigs(t *testing.T) {
convey.Convey("ActiveConfigs", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
configs, err := d.ActiveConfigs(c)
ctx.Convey("Then err should be nil.configs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(configs, convey.ShouldNotBeNil)
})
})
})
}
func TestGormAddBizConfig(t *testing.T) {
convey.Convey("AddBizConfig", t, func(ctx convey.C) {
var (
c = context.Background()
cfg = &business.BizCFG{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
lastid, err := d.AddBizConfig(c, cfg)
ctx.Convey("Then err should be nil.lastid should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(lastid, convey.ShouldNotBeNil)
})
})
})
}
func TestGormEditBizConfig(t *testing.T) {
convey.Convey("EditBizConfig", t, func(ctx convey.C) {
var (
c = context.Background()
cfg = &business.BizCFG{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.EditBizConfig(c, cfg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,80 @@
package gorm
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/business"
"github.com/smartystreets/goconvey/convey"
)
func TestEnableBusiness(t *testing.T) {
convey.Convey("EnableBusiness", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.EnableBusiness(c, 0)
ctx.Convey("Then err should be nil.cfgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDisableBusiness(t *testing.T) {
convey.Convey("DisableBusiness", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DisableBusiness(c, 0)
ctx.Convey("Then err should be nil.cfgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestBusiness(t *testing.T) {
convey.Convey("Business", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.Business(c, 0)
ctx.Convey("Then err should be nil.cfgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestBusinessList(t *testing.T) {
convey.Convey("BusinessList", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.BusinessList(c, 1, []int64{0}, true)
ctx.Convey("Then err should be nil.cfgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestUpdateBusiness(t *testing.T) {
convey.Convey("UpdateBusiness", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.UpdateBusiness(c, &business.Business{})
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,106 @@
package gorm
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/log"
)
// Available .
func Available(db *gorm.DB) *gorm.DB {
return db.Where("disable_time = '0000-00-00 00:00:00'")
}
// Disable .
func Disable(db *gorm.DB) *gorm.DB {
return db.Not("disable_time = '0000-00-00 00:00:00'")
}
func state(state string) func(db *gorm.DB) *gorm.DB {
state = strings.TrimSpace(state)
if state == net.StateAvailable {
return func(db *gorm.DB) *gorm.DB {
return Available(db)
}
} else if state == net.StateDisable {
return func(db *gorm.DB) *gorm.DB {
return Disable(db)
}
} else {
return func(db *gorm.DB) *gorm.DB {
return db
}
}
}
func pager(ps int64, pn int64, sort string) func(db *gorm.DB) *gorm.DB {
offset := ps * (pn - 1)
order := fmt.Sprintf("id %s", sort)
return func(db *gorm.DB) *gorm.DB {
return db.Limit(ps).Offset(offset).Order(order)
}
}
// UpdateFields .
func (d *Dao) UpdateFields(c context.Context, db *gorm.DB, table string, id int64, fields map[string]interface{}) (err error) {
if db == nil {
db = d.orm
}
if err = db.Table(table).Where("id=?", id).Updates(fields).Error; err != nil {
log.Error("UpdateFlow(%s,%d) error(%v) changed(%+v)", table, id, err, fields)
}
return
}
// AddItem .
func (d *Dao) AddItem(c context.Context, db *gorm.DB, n interface{}) (err error) {
if db == nil {
db = d.orm
}
if err = db.Create(n).Error; err != nil {
log.Error("AddItem error(%v) (%+v)", err, n)
}
return
}
// ColumnMapString .
func (d *Dao) ColumnMapString(c context.Context, table string, column string, ids []int64, where string) (result map[int64]string, err error) {
var (
rows *sql.Rows
id int64
value string
slt = fmt.Sprintf("`id`,`%s`", column)
)
result = map[int64]string{}
db := d.orm.Table(table).Select(slt).Where("id in (?)", ids)
where = strings.TrimSpace(where)
if where != "" {
db = db.Where(where)
}
rows, err = db.Rows()
if err == sql.ErrNoRows {
err = nil
return
}
if err != nil {
log.Error("ColumnMapString(%s, %s) rows error(%v) ids(%v)", table, column, err, ids)
return
}
defer rows.Close()
for rows.Next() {
if err = rows.Scan(&id, &value); err != nil {
log.Error("ColumnMapString(%s, %s) rows.scan error(%v) ids(%v)", table, column, err, ids)
return
}
result[id] = value
}
return
}

View File

@@ -0,0 +1,61 @@
package gorm
import (
"testing"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model/net"
)
func TestDaoAvailable(t *testing.T) {
var (
db = &gorm.DB{}
)
convey.Convey("Available", t, func(ctx convey.C) {
p1 := Available(db)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoDisable(t *testing.T) {
var (
db = &gorm.DB{}
)
convey.Convey("Disable", t, func(ctx convey.C) {
p1 := Disable(db)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaostatePager(t *testing.T) {
var (
s1 = ""
)
convey.Convey("state", t, func(ctx convey.C) {
p1 := state(s1)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDao_ColumnMapString(t *testing.T) {
var (
table = net.TableFlow
column = "ch_name"
ids = []int64{1, 2, 3}
)
convey.Convey("ColumnMapString", t, func(ctx convey.C) {
result, err := d.ColumnMapString(cntx, table, column, ids, "")
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
t.Logf("result(%+v)", result)
})
}

View File

@@ -0,0 +1,47 @@
package gorm
import (
"context"
"go-common/app/admin/main/aegis/conf"
"go-common/library/database/orm"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
// Dao dao
type Dao struct {
c *conf.Config
orm *gorm.DB
}
// New init mysql orm
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
orm: orm.NewMySQL(c.ORM),
}
dao.orm.LogMode(true)
return
}
// Close close the resource.
func (d *Dao) Close() {
d.orm.Close()
}
// BeginTx .
func (d *Dao) BeginTx(c context.Context) (tx *gorm.DB, err error) {
tx = d.orm.Begin()
if err = tx.Error; err != nil {
log.Error("orm begin tx error(%v)", err)
}
return
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return d.orm.DB().PingContext(c)
}

View File

@@ -0,0 +1,50 @@
package gorm
import (
"context"
"flag"
"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(err)
}
d = New(conf.Conf)
cntx = context.Background()
os.Exit(m.Run())
}
func TestDaoPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(context.TODO())
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,122 @@
package gorm
import (
"context"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
)
// DirectionByFlowID .
func (d *Dao) DirectionByFlowID(c context.Context, flowID []int64, direction int8) (dirs []*net.Direction, err error) {
dirs = []*net.Direction{}
db := d.orm.Where("flow_id in (?)", flowID)
if direction == net.DirInput || direction == net.DirOutput {
db = db.Where("direction=?", direction)
}
err = db.Scopes(Available).Find(&dirs).Error
if err != nil {
log.Error("DirectionByFlowID find error(%v) flowid(%v) direction(%d)", err, flowID, direction)
}
return
}
// DirectionByTransitionID .
func (d *Dao) DirectionByTransitionID(c context.Context, transitionID []int64, direction int8, onlyAvailable bool) (dirs []*net.Direction, err error) {
dirs = []*net.Direction{}
db := d.orm.Where("transition_id in (?)", transitionID)
if direction == net.DirInput || direction == net.DirOutput {
db = db.Where("direction=?", direction)
}
if onlyAvailable {
db = db.Scopes(Available)
}
err = db.Find(&dirs).Error
if err != nil {
log.Error("DirectionByTransitionID find error(%v) transitionid(%v) direction(%d)", err, transitionID, direction)
}
return
}
// DirectionByID .
func (d *Dao) DirectionByID(c context.Context, id int64) (n *net.Direction, err error) {
n = &net.Direction{}
err = d.orm.Where("id=?", id).First(n).Error
if err == gorm.ErrRecordNotFound {
err = ecode.NothingFound
return
}
if err != nil {
log.Error("DirectionByID(%+v) error(%v)", id, err)
}
return
}
func (d *Dao) Directions(c context.Context, ids []int64) (n []*net.Direction, err error) {
n = []*net.Direction{}
if err = d.orm.Where("id in (?)", ids).Find(&n).Error; err != nil {
log.Error("Directions error(%v) ids(%v)", err, ids)
}
return
}
// DirectionList .
func (d *Dao) DirectionList(c context.Context, pm *net.ListDirectionParam) (result *net.ListDirectionRes, err error) {
result = &net.ListDirectionRes{
Pager: net.Pager{
Num: pm.Pn,
Size: pm.Ps,
},
}
db := d.orm.Table(net.TableDirection).Where("net_id=?", pm.NetID)
if len(pm.ID) > 0 {
db = db.Where("id in (?)", pm.ID)
}
if pm.FlowID > 0 {
db = db.Where("flow_id=?", pm.FlowID)
}
if pm.TransitionID > 0 {
db = db.Where("transition_id=?", pm.TransitionID)
}
if pm.Direction == net.DirInput || pm.Direction == net.DirOutput {
db = db.Where("direction=?", pm.Direction)
}
err = db.Scopes(state(pm.State)).Count(&result.Pager.Total).Scopes(pager(pm.Ps, pm.Pn, pm.Sort)).Find(&result.Result).Error
if err != nil {
log.Error("DirectionList find error(%v) params(%+v)", err, pm)
}
return
}
// DirectionByUnique .
func (d *Dao) DirectionByUnique(c context.Context, netID int64, flowID int64, transitionID int64, direction int8) (t *net.Direction, err error) {
t = &net.Direction{}
err = d.orm.Where("net_id=? AND flow_id=? AND transition_id=? AND direction=?", netID, flowID, transitionID, direction).
First(t).Error
if err == gorm.ErrRecordNotFound {
err = nil
t = nil
return
}
if err != nil {
log.Error("DirectionByUnique(%d,%d,%d,%d) error(%v)", netID, flowID, transitionID, direction, err)
}
return
}
// DirectionByNet .
func (d *Dao) DirectionByNet(c context.Context, netID int64) (n []*net.Direction, err error) {
n = []*net.Direction{}
err = d.orm.Where("net_id=?", netID).Scopes(Available).Find(&n).Error
if err != nil {
log.Error("DirectionByNet(%d) error(%v)", netID, err)
}
return
}

View File

@@ -0,0 +1,89 @@
package gorm
import (
"testing"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoDirectionByTransitionID(t *testing.T) {
convey.Convey("DirectionByTransitionID", t, func(ctx convey.C) {
_, err := d.DirectionByTransitionID(cntx, []int64{}, 1, true)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDirectionByID(t *testing.T) {
convey.Convey("DirectionByID", t, func(ctx convey.C) {
_, err := d.DirectionByID(cntx, -1)
ctx.Convey("Then err should be 404", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, ecode.NothingFound)
})
})
}
func TestDaoDirectionList(t *testing.T) {
var (
pm = &net.ListDirectionParam{
NetID: 1,
Ps: 20,
ID: []int64{1},
FlowID: 1,
TransitionID: 1,
Direction: 1,
}
)
convey.Convey("DirectionList", t, func(ctx convey.C) {
result, err := d.DirectionList(cntx, pm)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
t.Logf("list result(%+v)", result)
for _, dir := range result.Result {
t.Logf("bylist dir(%+v)", dir)
}
})
})
}
func TestDaoDirectionByUnique(t *testing.T) {
convey.Convey("DirectionByUnique", t, func(ctx convey.C) {
_, err := d.DirectionByUnique(cntx, 0, 0, 0, 0)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDirectionByFlowID(t *testing.T) {
convey.Convey("DirectionByFlowID", t, func(ctx convey.C) {
_, err := d.DirectionByFlowID(cntx, []int64{}, 1)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDirectionByNet(t *testing.T) {
convey.Convey("DirectionByNet", t, func(ctx convey.C) {
_, err := d.DirectionByNet(cntx, 0)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDirections(t *testing.T) {
convey.Convey("Directions", t, func(ctx convey.C) {
_, err := d.Directions(cntx, []int64{0})
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,105 @@
package gorm
import (
"context"
"strings"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
)
// FlowByID .
func (d *Dao) FlowByID(c context.Context, id int64) (f *net.Flow, err error) {
f = &net.Flow{}
err = d.orm.Where("id=?", id).First(f).Error
if err == gorm.ErrRecordNotFound {
err = ecode.AegisFlowNotFound
return
}
if err != nil {
log.Error("FlowByID(%+v) error(%v)", id, err)
}
return
}
// FlowList .
func (d *Dao) FlowList(c context.Context, pm *net.ListNetElementParam) (result *net.ListFlowRes, err error) {
result = &net.ListFlowRes{
Pager: net.Pager{
Num: pm.Pn,
Size: pm.Ps,
},
}
db := d.orm.Table(net.TableFlow).Where("net_id=?", pm.NetID)
if len(pm.ID) > 0 {
db = db.Where("id in (?)", pm.ID)
}
pm.Name = strings.TrimSpace(pm.Name)
if pm.Name != "" {
db = db.Where("name=?", pm.Name)
}
err = db.Scopes(state(pm.State)).Count(&result.Pager.Total).Scopes(pager(pm.Ps, pm.Pn, pm.Sort)).Find(&result.Result).Error
if err != nil {
log.Error("FlowList find error(%v) params(%+v)", err, pm)
}
return
}
// FlowByUnique .
func (d *Dao) FlowByUnique(c context.Context, netID int64, name string) (f *net.Flow, err error) {
f = &net.Flow{}
err = d.orm.Where("net_id=? AND name=?", netID, name).First(f).Error
if err == gorm.ErrRecordNotFound {
err = nil
f = nil
return
}
if err != nil {
log.Error("FlowByUnique(%d,%s) error(%v)", netID, name, err)
}
return
}
// Flows .
func (d *Dao) Flows(c context.Context, ids []int64) (fs []*net.Flow, err error) {
fs = []*net.Flow{}
err = d.orm.Where("id in (?)", ids).Find(&fs).Error
if err != nil {
log.Error("Flows(%v) error(%v)", ids, err)
}
return
}
// FlowsByNet .
func (d *Dao) FlowsByNet(c context.Context, netID []int64) (fs []*net.Flow, err error) {
fs = []*net.Flow{}
err = d.orm.Scopes(Available).Where("net_id in (?)", netID).Order("id ASC").Find(&fs).Error
if err != nil {
log.Error("Flows(%d) error(%v)", netID, err)
}
return
}
func (d *Dao) FlowIDByNet(c context.Context, nid []int64) (res map[int64][]int64, err error) {
res = map[int64][]int64{}
listi := []struct {
ID int64 `gorm:"column:id"`
NetID int64 `gorm:"column:net_id"`
}{}
if err = d.orm.Table(net.TableFlow).Select("id,net_id").
Where("net_id in (?)", nid).Scopes(Available).Scan(&listi).Error; err != nil {
log.Error("FlowIDByNet error(%v) nid(%v)", err, nid)
return
}
for _, item := range listi {
res[item.NetID] = append(res[item.NetID], item.ID)
}
return
}

View File

@@ -0,0 +1,70 @@
package gorm
import (
"context"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/log"
)
// FRByFlow .
func (d *Dao) FRByFlow(c context.Context, flowID []int64) (fr *net.FlowResource, err error) {
fr = &net.FlowResource{}
if err = d.orm.Where("flow_id in (?)", flowID).First(fr).Error; err == gorm.ErrRecordNotFound {
fr = nil
err = nil
return
}
if err != nil {
log.Error("FRByFlow error(%v) flowid(%v)", err, flowID)
}
return
}
// FRByNetRID .
func (d *Dao) FRByNetRID(c context.Context, netID []int64, rids []int64, onlyRunning bool) (frs []*net.FlowResource, err error) {
frs = []*net.FlowResource{}
db := d.orm.Where("rid in (?) AND net_id in (?)", rids, netID)
if onlyRunning {
db = db.Scopes(running)
}
if err = db.Find(&frs).Error; err != nil {
log.Error("FRByNetRID error(%v) netid(%v) rids(%v)", err, netID, rids)
}
return
}
// FRByUniques .
func (d *Dao) FRByUniques(c context.Context, rids []int64, flowID []int64, onlyRunning bool) (frs []*net.FlowResource, err error) {
frs = []*net.FlowResource{}
db := d.orm
if len(rids) > 0 {
db = db.Where("rid in (?)", rids)
}
if len(flowID) > 0 {
db = db.Where("flow_id in (?)", flowID)
}
if onlyRunning {
db = db.Scopes(running)
}
if err = db.Find(&frs).Error; err != nil {
log.Error("FRByUniques error(%v) rids(%+v) flowid(%d)", err, rids, flowID)
}
return
}
// CancelFlowResource .
func (d *Dao) CancelFlowResource(c context.Context, tx *gorm.DB, rids []int64) (err error) {
fields := map[string]interface{}{"state": net.FRStateDeleted}
if err = tx.Table(net.TableFlowResource).Where("rid in (?)", rids).Updates(fields).Error; err != nil {
log.Error("CancelFlowResource error(%v) rids(%+v)", err, rids)
}
return
}
func running(db *gorm.DB) *gorm.DB {
return db.Where("state!=?", net.FRStateDeleted)
}

View File

@@ -0,0 +1,45 @@
package gorm
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoFRByFlow(t *testing.T) {
convey.Convey("FRByFlow", t, func(ctx convey.C) {
_, err := d.FRByFlow(cntx, []int64{})
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFRByNetRID(t *testing.T) {
convey.Convey("FRByNetRID", t, func(ctx convey.C) {
_, err := d.FRByNetRID(cntx, []int64{}, []int64{}, false)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFRByUniques(t *testing.T) {
convey.Convey("FRByUniques", t, func(ctx convey.C) {
_, err := d.FRByUniques(cntx, []int64{1}, []int64{1}, true)
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCancelFlowResource(t *testing.T) {
tx, _ := d.BeginTx(cntx)
defer tx.Commit()
convey.Convey("CancelFlowResource", t, func(ctx convey.C) {
err := d.CancelFlowResource(cntx, tx, []int64{})
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,73 @@
package gorm
import (
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model/net"
)
func TestDaoFlowByID(t *testing.T) {
convey.Convey("FlowByID", t, func(ctx convey.C) {
_, err := d.FlowByID(cntx, 1)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFlowList(t *testing.T) {
var (
pm = &net.ListNetElementParam{
NetID: 1,
State: net.StateAvailable,
Ps: 5,
Pn: 2,
ID: []int64{1},
Name: "name",
}
)
convey.Convey("FlowList", t, func(ctx convey.C) {
result, err := d.FlowList(cntx, pm)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoFlowByUnique(t *testing.T) {
convey.Convey("FlowByUnique", t, func(ctx convey.C) {
_, err := d.FlowByUnique(cntx, 0, "")
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFlowsByNet(t *testing.T) {
convey.Convey("FlowsByNet", t, func(ctx convey.C) {
_, err := d.FlowsByNet(cntx, []int64{})
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFlows(t *testing.T) {
convey.Convey("Flows", t, func(ctx convey.C) {
_, err := d.Flows(cntx, []int64{})
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFlowIDByNet(t *testing.T) {
convey.Convey("FlowIDByNet", t, func(ctx convey.C) {
_, err := d.FlowIDByNet(cntx, []int64{})
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,120 @@
package gorm
import (
"context"
"time"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
// NetByID .
func (d *Dao) NetByID(c context.Context, id int64) (n *net.Net, err error) {
n = &net.Net{}
err = d.orm.Where("id=?", id).First(n).Error
if err == gorm.ErrRecordNotFound {
err = ecode.NothingFound
return
}
if err != nil {
log.Error("NetByID(%+v) error(%v)", id, err)
}
return
}
func (d *Dao) Nets(c context.Context, ids []int64) (n []*net.Net, err error) {
n = []*net.Net{}
if err = d.orm.Where("id in (?)", ids).Find(&n).Error; err != nil {
log.Error("Nets error(%v) ids(%v)", err, ids)
}
return
}
// NetByUnique .
func (d *Dao) NetByUnique(c context.Context, name string) (n *net.Net, err error) {
n = &net.Net{}
err = d.orm.Where("ch_name=?", name).First(n).Error
if err == gorm.ErrRecordNotFound {
err = nil
n = nil
return
}
if err != nil {
log.Error("NetByUnique(%+v) error(%v)", name, err)
}
return
}
// NetList .
func (d *Dao) NetList(c context.Context, pm *net.ListNetParam) (result *net.ListNetRes, err error) {
result = &net.ListNetRes{
Pager: net.Pager{
Num: pm.Pn,
Size: pm.Ps,
},
}
db := d.orm.Table(net.TableNet)
if len(pm.ID) > 0 {
db = db.Where("id in (?)", pm.ID)
}
if pm.BusinessID > 0 {
db = db.Where("business_id=?", pm.BusinessID)
}
err = db.Scopes(state(pm.State)).Count(&result.Pager.Total).Scopes(pager(pm.Ps, pm.Pn, pm.Sort)).Find(&result.Result).Error
if err != nil {
log.Error("NetList find error(%v) params(%+v)", err, pm)
}
return
}
// NetBindStartFlow .
func (d *Dao) NetBindStartFlow(c context.Context, tx *gorm.DB, id int64, flowID int64) (err error) {
if err = d.UpdateFields(c, tx, net.TableNet, id, map[string]interface{}{"start_flow_id": flowID}); err != nil {
log.Error("NetBindStartFlow d.UpdateFields error(%v) id(%d) flowid(%d)", err, id, flowID)
}
return
}
// NetIDByBusiness .
func (d *Dao) NetIDByBusiness(c context.Context, businessID []int64) (bizmap map[int64][]int64, err error) {
res := []struct {
ID int64 `gorm:"column:id"`
BusinessID int64 `gorm:"column:business_id"`
}{}
list := []*net.Net{}
bizmap = map[int64][]int64{}
if err = d.orm.Select("id, business_id").Where("business_id in (?)", businessID).
Scopes(Available).Find(&list).Scan(&res).Error; err != nil {
return
}
for _, item := range res {
bizmap[item.BusinessID] = append(bizmap[item.BusinessID], item.ID)
}
return
}
// NetsByBusiness .
func (d *Dao) NetsByBusiness(c context.Context, businessID []int64, onlyAvailable bool) (list []*net.Net, err error) {
list = []*net.Net{}
db := d.orm
if len(businessID) > 0 {
db = db.Where("business_id in (?)", businessID)
}
if onlyAvailable {
db = db.Scopes(Available)
}
if err = db.Find(&list).Error; err != nil {
log.Error("NetsByBusiness(%v) error(%v) onlyavailable(%v)", businessID, err, onlyAvailable)
}
return
}
// DisableNet .
func (d *Dao) DisableNet(c context.Context, tx *gorm.DB, id int64) (err error) {
err = d.UpdateFields(c, tx, net.TableNet, id, map[string]interface{}{"disable_time": time.Now()})
return
}

View File

@@ -0,0 +1,93 @@
package gorm
import (
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model/net"
)
func TestDaoNetByID(t *testing.T) {
convey.Convey("NetByID", t, func(ctx convey.C) {
d.NetByID(cntx, 1)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
})
})
}
func TestDao_NetList(t *testing.T) {
convey.Convey("NetList", t, func(ctx convey.C) {
pm := &net.ListNetParam{
BusinessID: 1,
//State: net.StateAvailable,
Ps: 20,
Pn: 1,
ID: []int64{1},
}
_, err := d.NetList(cntx, pm)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDaoNetIDByBusiness(t *testing.T) {
convey.Convey("NetIDByBusiness", t, func(ctx convey.C) {
res, err := d.NetIDByBusiness(cntx, []int64{1, 2, 3})
t.Logf("res(%+v)", res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoNetsByBusiness(t *testing.T) {
convey.Convey("NetsByBusiness", t, func(ctx convey.C) {
_, err := d.NetsByBusiness(cntx, []int64{1}, true)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoNets(t *testing.T) {
convey.Convey("Nets", t, func(ctx convey.C) {
_, err := d.Nets(cntx, []int64{})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoNetByUnique(t *testing.T) {
convey.Convey("NetByUnique", t, func(ctx convey.C) {
_, err := d.NetByUnique(cntx, "")
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoNetBindStartFlow(t *testing.T) {
var (
tx, _ = d.BeginTx(cntx)
)
defer tx.Commit()
convey.Convey("NetBindStartFlow", t, func(ctx convey.C) {
err := d.NetBindStartFlow(cntx, tx, 0, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDisableNet(t *testing.T) {
var (
tx, _ = d.BeginTx(cntx)
)
defer tx.Commit()
convey.Convey("DisableNet", t, func(ctx convey.C) {
err := d.DisableNet(cntx, tx, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,67 @@
package gorm
import (
"context"
"database/sql"
"go-common/app/admin/main/aegis/model"
"go-common/library/log"
)
//ReportTaskMetas 任务数据统计
func (d *Dao) ReportTaskMetas(c context.Context, bt string, et string, bizid, flowid int64, uids []int64, mnames map[int64]string, tp int8) (metas []*model.ReportMeta, missuid []int64, err error) {
db := d.orm.Table("task_report").Select("mtime,uid,type,content").Where("business_id=? AND type=?", bizid, tp)
if flowid != 0 {
db.Where("flow_id=?", flowid)
}
db = db.Where("mtime>=? AND mtime<?", bt, et)
if len(uids) > 0 {
db = db.Where("uid IN (?)", uids)
}
var rows *sql.Rows
if rows, err = db.Order("mtime asc").Rows(); err != nil {
log.Error("ReportTaskFlow error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
meta := &model.ReportMeta{}
if err = rows.Scan(&meta.Mtime, &meta.UID, &meta.Type, &meta.Content); err != nil {
return
}
if uname, ok := mnames[meta.UID]; ok {
meta.Uname = uname
} else {
missuid = append(missuid, meta.UID)
}
metas = append(metas, meta)
}
return
}
//TaskReports 任务报表记录
func (d *Dao) TaskReports(c context.Context, biz int64, flowID int64, tp []int8, statdateFrom string, statdateTo string) (res []*model.TaskReport, err error) {
res = []*model.TaskReport{}
db := d.orm
if statdateFrom != "" {
db = db.Where("stat_date>=?", statdateFrom)
}
if statdateTo != "" {
db = db.Where("stat_date <=?", statdateTo)
}
db = db.Where("business_id=?", biz)
if flowID > 0 {
db = db.Where("flow_id=?", flowID)
}
if len(tp) >= 0 {
db = db.Where("type in (?)", tp)
}
db = db.Order("stat_date desc, business_id desc, flow_id desc")
if err = db.Find(&res).Error; err != nil {
log.Error("TaskReports error(%v)", err)
}
return
}

View File

@@ -0,0 +1,40 @@
package gorm
import (
"context"
"fmt"
"testing"
"github.com/smartystreets/goconvey/convey"
"time"
)
func TestGormReportTaskFlow(t *testing.T) {
convey.Convey("ReportTaskFlow", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
metas, _, err := d.ReportTaskMetas(c, "", "", 1, 1, []int64{}, map[int64]string{}, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
for _, meta := range metas {
fmt.Println("meta:", meta)
}
})
})
})
}
func TestDao_TaskReports(t *testing.T) {
time.Time{}.Unix()
t.Logf("%s", time.Duration(time.Duration(3661)*time.Second).String())
return
convey.Convey("TaskReports", t, func(ctx convey.C) {
res, err := d.TaskReports(cntx, 1, 1, []int8{2, 3, 4}, "2019-01-14", "2019-01-15")
ctx.So(err, convey.ShouldBeNil)
for _, item := range res {
t.Logf("item(%+v)", item)
}
})
}

View File

@@ -0,0 +1,304 @@
package gorm
import (
"context"
"database/sql"
"encoding/json"
"go-common/app/admin/main/aegis/model/resource"
"go-common/library/log"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model"
)
const (
_resourceResSQL = "SELECT r.id, r.business_id, r.oid, r.mid,r.content,r.extra1,r.extra2,r.extra3,r.extra4,r.extra1s,r.extra2s,r.metadata, rr.attribute, rr.note, rr.reject_reason, rr.reason_id, rr.state, rr.pubtime, rr.deltime " +
"FROM resource r LEFT JOIN resource_result rr ON r.id = rr.rid WHERE r.id = ?"
_resByOIDSQL = "SELECT r.id, r.business_id, r.oid, r.mid,r.content,r.extra1,r.extra2,r.extra3,r.extra4,r.extra1s,r.extra2s,r.metadata, rr.attribute, rr.note, rr.reject_reason, rr.reason_id, rr.state, rr.pubtime, rr.deltime " +
"FROM resource r LEFT JOIN resource_result rr ON r.id = rr.rid WHERE r.business_id = ? AND r.oid = ?"
)
var _changeableFields = map[string]struct{}{
"extra1": {},
"extra2": {},
"extra3": {},
"extra4": {},
"extra5": {},
"extra6": {},
"extra1s": {},
"extra2s": {},
"extra3s": {},
"extra4s": {},
"extratime1": {},
}
// ListHelperForTask 补充任务列表里面的oid和content
func (d *Dao) ListHelperForTask(c context.Context, rids []int64) (res map[int64][]interface{}, err error) {
var (
rows *sql.Rows
id int64
oid, content, metadata string
)
if rows, err = d.orm.Table("resource").Select("id,oid,content,metadata").Where("id IN (?)", rids).Rows(); err != nil {
log.Error("listHelperForTask err(%v)", err)
return
}
res = make(map[int64][]interface{})
defer rows.Close()
for rows.Next() {
if err = rows.Scan(&id, &oid, &content, &metadata); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
metas := make(map[string]interface{})
if len(metadata) > 0 {
if err = json.Unmarshal([]byte(metadata), &metas); err != nil {
log.Error("ListHelperForTask err(%+v)\n", err)
}
err = nil
}
res[id] = []interface{}{oid, content, metas}
}
return
}
// TxAddResource .
func (d *Dao) TxAddResource(tx *gorm.DB, r *resource.Resource, rr *resource.Result) (rid int64, err error) {
err = tx.Table("resource").Where("business_id=? AND oid=?", r.BusinessID, r.OID).
Assign(map[string]interface{}{
"oid": r.OID,
"content": r.Content,
"extra1": r.Extra1,
"extra2": r.Extra2,
"extra3": r.Extra3,
"extra4": r.Extra4,
"extra1s": r.Extra1s,
"extra2s": r.Extra2s,
"metadata": r.MetaData,
"extra5": r.Extra5,
"extra6": r.Extra6,
"extra3s": r.Extra3s,
"extra4s": r.Extra4s,
"extratime1": r.ExtraTime1,
"octime": r.OCtime,
"ptime": r.Ptime,
}).FirstOrCreate(&r).Error
if err != nil {
return
}
rid = r.ID
rr.RID = r.ID
err = tx.Table("resource_result").Where("rid=?", rr.RID).Assign(map[string]interface{}{
"attribute": rr.Attribute,
"note": rr.Note,
"reject_reason": rr.RejectReason,
"reason_id": rr.ReasonID,
"state": rr.State,
"pubtime": rr.PubTime,
"deltime": rr.DelTime,
}).FirstOrCreate(&rr).Error
return
}
// ResourceByOID .
func (d *Dao) ResourceByOID(c context.Context, OID string, bizID int64) (res *resource.Resource, err error) {
res = &resource.Resource{}
if err = d.orm.Where("oid = ? AND business_id = ?", OID, bizID).First(res).Error; err == gorm.ErrRecordNotFound {
res = nil
err = nil
}
return
}
// RidsByOids .
func (d *Dao) RidsByOids(c context.Context, bizID int64, oids []string) (rids string, err error) {
err = d.orm.Table("resource").Select("GROUP_CONCAT(id)").Where("business_id=? AND oid IN (?)", bizID, oids).Row().Scan(&rids)
return
}
// OidByRID 通过rid查到oid
func (d *Dao) OidByRID(c context.Context, rid int64) (oid string, err error) {
if err = d.orm.Table("resource").Select("oid").Where("id=?", rid).Row().Scan(&oid); err == sql.ErrNoRows {
err = nil
}
return
}
// TxUpdateResult .
func (d *Dao) TxUpdateResult(ormTx *gorm.DB, rid int64, res map[string]interface{}, rscRes *resource.Result) (err error) {
params := make(map[string]interface{})
for k, v := range res {
if k != "state" && k != "attribute" {
continue
}
params[k] = v
}
db := ormTx.Table("resource_result").
Where("rid = ?", rid)
//Update(params)
if rscRes != nil {
if rscRes.Attribute != -1 {
params["attribute"] = rscRes.Attribute
}
if rscRes.Note != "" {
params["note"] = rscRes.Note
}
if rscRes.RejectReason != "" {
params["reject_reason"] = rscRes.RejectReason
}
if rscRes.ReasonID != 0 {
params["reason_id"] = rscRes.ReasonID
}
}
return db.Update(params).Error
}
// TxUpdateResource . TODO Resource表的字段要不要直接审核提交变更 还是等待业务方同步更新?(例如单话的上线下线)
func (d *Dao) TxUpdateResource(ormTx *gorm.DB, rid int64, res map[string]interface{}) (err error) {
params := make(map[string]interface{})
for k, v := range res {
if _, ok := _changeableFields[k]; !ok {
continue
}
params[k] = v
}
return ormTx.Table("resource").Where("id = ?", rid).Update(params).Error
}
// TxUpdateState 更新状态
func (d *Dao) TxUpdateState(tx *gorm.DB, rids []int64, state int) (err error) {
return tx.Table("resource_result").Where("rid IN (?)", rids).Update("state", state).Error
}
// UpdateResource 更新资源
func (d *Dao) UpdateResource(c context.Context, bizid int64, oid string, update map[string]interface{}) (rows int64, err error) {
db := d.orm.Table("resource").Where("business_id=? AND oid=?", bizid, oid).Update(update)
return db.RowsAffected, db.Error
}
// ResourceRes .
func (d *Dao) ResourceRes(c context.Context, rid int64) (res *resource.Res, err error) {
res = &resource.Res{}
if err = d.orm.Raw(_resourceResSQL, rid).Scan(res).Error; err == gorm.ErrRecordNotFound {
res = nil
err = nil
}
return
}
// ResByOID .
func (d *Dao) ResByOID(c context.Context, bizID int64, OID string) (res *resource.Res, err error) {
res = &resource.Res{}
if err = d.orm.Raw(_resByOIDSQL, bizID, OID).Scan(res).Error; err == gorm.ErrRecordNotFound {
res = nil
err = nil
}
return
}
//ResOIDByID 根据id获取资源oid
func (d *Dao) ResOIDByID(c context.Context, rids []int64) (res map[int64]string, err error) {
list := []struct {
ID int64 `gorm:"column:id"`
OID string `gorm:"column:oid"`
}{}
res = map[int64]string{}
if err = d.orm.Table("resource").Select("id,oid").Where("id in (?)", rids).Find(&list).Error; err != nil {
log.Error("ResOIDByID error(%v) rids(%v)", err, rids)
return
}
for _, item := range list {
res[item.ID] = item.OID
}
return
}
//ResIDByOID 根据oid获取rid
func (d *Dao) ResIDByOID(C context.Context, bizID int64, oids []string) (res map[string]int64, err error) {
list := []struct {
ID int64 `gorm:"column:id"`
OID string `gorm:"column:oid"`
}{}
res = map[string]int64{}
if err = d.orm.Table("resource").Select("id,oid").Where("business_id=? and oid in (?)", bizID, oids).Find(&list).Error; err != nil {
log.Error("ResIDByOID error(%v) oids(%v)", err, oids)
return
}
for _, item := range list {
res[item.OID] = item.ID
}
return
}
//ResourceHit 根据状态筛选资源
func (d *Dao) ResourceHit(c context.Context, rids []int64) (hitids map[int64]int64, err error) {
hitids = make(map[int64]int64)
rows, err := d.orm.Table("resource_result").Select("rid,state").Where("rid IN (?)", rids).Rows()
if err != nil {
log.Error("ResourceHitState error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var rid, state int64
if err = rows.Scan(&rid, &state); err != nil {
log.Error("ResourceHitState error(%v)", err)
}
hitids[rid] = state
}
return
}
//ResultByRID result by rid
func (d *Dao) ResultByRID(c context.Context, rid int64) (res *resource.Result, err error) {
res = &resource.Result{}
if err = d.orm.Where("rid=?", rid).First(&res).Error; err == gorm.ErrRecordNotFound {
log.Error("ResultByRID rid(%d) error(%v)", rid, err)
}
return
}
//MetaByRID .
func (d *Dao) MetaByRID(c context.Context, rids []int64) (metas map[int64]string, err error) {
var rows *sql.Rows
metas = make(map[int64]string)
rows, err = d.orm.Table("resource").Select("id,metadata").Where("id IN (?)", rids).Rows()
if err != nil {
log.Error("MetaByRID Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var (
id int64
meta string
)
if err = rows.Scan(&id, &meta); err != nil {
log.Error("MetaByRID rows.Scan error(%v)", err)
return
}
metas[id] = meta
}
return
}
//UpsertByOIDs 获取需要更新到搜索部分
func (d *Dao) UpsertByOIDs(c context.Context, businessID int64, oids []string) (res []*model.UpsertItem, err error) {
res = []*model.UpsertItem{}
sqlstr := `SELECT r.id,r.extra1,r.extra2,r.extra3,r.extra4,rr.state
FROM resource r
LEFT JOIN resource_result rr ON r.id=rr.rid
WHERE r.business_id=? AND r.oid IN (?)`
if err = d.orm.Raw(sqlstr, businessID, oids).Find(&res).Error; err != nil {
log.Error("UpsertByOIDs error(%+v) businessid(%d) oids(%+v)", err, businessID, oids)
}
return
}

View File

@@ -0,0 +1,220 @@
package gorm
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/resource"
"github.com/smartystreets/goconvey/convey"
)
func TestGormListHelperForTask(t *testing.T) {
convey.Convey("ListHelperForTask", t, func(ctx convey.C) {
var (
c = context.Background()
rids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ListHelperForTask(c, rids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestGormResourceByOID(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("ResourceByOID", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ResourceByOID(c, "", 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormOidByRID(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("OidByRID", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.OidByRID(c, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormTxUpdateResult(t *testing.T) {
convey.Convey("TxUpdateResult", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTx(context.TODO())
rid = int64(0)
res = map[string]interface{}{"extra1": 1}
rscRes = &resource.Result{}
)
defer tx.Commit()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.TxUpdateResult(tx, rid, res, rscRes)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormResourceRes(t *testing.T) {
convey.Convey("ResourceRes", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ResourceRes(context.TODO(), 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormResByOID(t *testing.T) {
convey.Convey("ResByOID", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ResByOID(context.TODO(), 0, "")
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormUpdateResource(t *testing.T) {
convey.Convey("UpdateResource", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
d.UpdateResource(context.TODO(), 1, "xyz", map[string]interface{}{"mid": 123})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
})
})
})
}
func TestGormResOIDByID(t *testing.T) {
convey.Convey("ResOIDByID", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.ResOIDByID(context.TODO(), []int64{1, 2})
t.Logf("res(%+v)", res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormResIDByOID(t *testing.T) {
convey.Convey("ResIDByOID", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.ResIDByOID(context.TODO(), 1, []string{"1", "2"})
t.Logf("res(%+v)", res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormResourceHit(t *testing.T) {
convey.Convey("ResourceHit", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, err := d.ResourceHit(context.TODO(), []int64{})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormResultByRID(t *testing.T) {
convey.Convey("ResultByRID", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
d.ResultByRID(context.TODO(), 50)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
})
})
})
}
func TestGormRidsByOids(t *testing.T) {
convey.Convey("RidsByOids", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
d.RidsByOids(cntx, 0, []string{})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
})
})
})
}
func TestGormTxUpdateResource(t *testing.T) {
convey.Convey("TxUpdateResource", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTx(context.TODO())
rid = int64(0)
res = map[string]interface{}{"extra1": 1}
)
defer tx.Commit()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.TxUpdateResource(tx, rid, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormTxUpdateState(t *testing.T) {
convey.Convey("TxUpdateState", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTx(context.TODO())
rids = []int64{0}
)
defer tx.Commit()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.TxUpdateState(tx, rids, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormMetaByRID(t *testing.T) {
convey.Convey("MetaByRID", t, func(ctx convey.C) {
var (
rids = []int64{0}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.MetaByRID(cntx, rids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestGormUpsertByOIDs(t *testing.T) {
convey.Convey("UpsertByOIDs", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.UpsertByOIDs(context.TODO(), 1, []string{"oid000001", "oid000002"})
for _, item := range res {
t.Logf("res(%+v)", item)
}
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,146 @@
package gorm
import (
"context"
"database/sql"
"go-common/app/admin/main/aegis/model/task"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
const (
_submitSQL = "UPDATE task SET state=?,uid=?,utime=? WHERE id=? AND state=? AND uid=?"
)
// TxSubmit 提交任务
func (d *Dao) TxSubmit(tx *gorm.DB, opt *task.SubmitOptions, state int8) (rows int64, err error) {
rows = tx.Exec(_submitSQL, state, opt.UID, opt.Utime, opt.TaskID, opt.OldState, opt.OldUID).RowsAffected
return
}
// TxCloseTasks close
func (d *Dao) TxCloseTasks(tx *gorm.DB, rids []int64, uid int64) (err error) {
err = tx.Table("task").Where("rid IN (?) AND state<?", rids, task.TaskStateSubmit).Update("state", task.TaskStateClosed).Update("uid", uid).Error
return
}
// CloseTask .
func (d *Dao) CloseTask(c context.Context, id int64) (err error) {
return d.orm.Table("task").Where("id=?", id).Update("state", task.TaskStateClosed).Update("uid", 399).Error
}
// TaskByRID task by rid
func (d *Dao) TaskByRID(c context.Context, rid, flowid int64) (t *task.Task, err error) {
db := d.orm.Model(&task.Task{}).Where("rid = ? AND state<?", rid, task.TaskStateSubmit)
if flowid > 0 {
db = db.Where("flow_id=?", flowid)
}
t = &task.Task{}
if err = db.Find(t).Error; err == gorm.ErrRecordNotFound {
err = nil
t = nil
}
return
}
// MaxWeight max weight
func (d *Dao) MaxWeight(c context.Context, bizID, flowID int64) (max int64, err error) {
if err = d.orm.Table("task").Select("max(weight)").Where("business_id = ? AND flow_id = ?", bizID, flowID).
Where("state = ? OR state = ?", task.TaskStateInit, task.TaskStateDispatch).Row().Scan(&max); err != nil {
max = 0
err = nil
}
return
}
// UndoStat 未完成
func (d *Dao) UndoStat(c context.Context, bizID, flowID, UID int64) (stat *task.UnDOStat, err error) {
stat = &task.UnDOStat{}
err = d.orm.Raw(`SELECT COUNT(CASE WHEN admin_id>0 AND state = 0 THEN 1 ELSE NULL END) assign,
COUNT(CASE WHEN admin_id = 0 AND state = 2 THEN 1 ELSE NULL END) delay,
COUNT(CASE WHEN admin_id = 0 AND state = 1 THEN 1 ELSE NULL END) normal
FROM task WHERE business_id=? AND flow_id=? AND uid=?`, bizID, flowID, UID).Scan(stat).Error
return
}
// TaskStat 任务详情统计
func (d *Dao) TaskStat(c context.Context, bizID, flowID, UID int64) (stat *task.Stat, err error) {
stat = &task.Stat{}
err = d.orm.Raw(`SELECT COUNT(CASE WHEN admin_id=0 AND state = 0 THEN 1 ELSE NULL END) normal,
COUNT(CASE WHEN admin_id>0 AND state = 0 THEN 1 ELSE NULL END) assign,
COUNT(CASE WHEN state=2 THEN 1 ELSE NULL END) delayTotal,
COUNT(CASE WHEN uid=? AND state=2 THEN 1 ELSE NULL END) delayPersonal
FROM task WHERE business_id=? AND flow_id=?`, UID, bizID, flowID).Scan(stat).Error
return
}
// TaskListSeized 停滞任务
func (d *Dao) TaskListSeized(c context.Context, opt *task.ListOptions) (ids []int64, count int64, err error) {
return d.tasklist(c, "seized", opt.BusinessID, opt.FlowID, opt.UID, opt.Pn, opt.Ps)
}
// TaskListDelayd 延迟任务
func (d *Dao) TaskListDelayd(c context.Context, opt *task.ListOptions) (ids []int64, count int64, err error) {
return d.tasklist(c, "delayd", opt.BusinessID, opt.FlowID, opt.UID, opt.Pn, opt.Ps)
}
// TaskListAssignd 指派停滞任务
func (d *Dao) TaskListAssignd(c context.Context, opt *task.ListOptions) (ids []int64, count int64, err error) {
return d.tasklist(c, "assignd", opt.BusinessID, opt.FlowID, opt.UID, opt.Pn, opt.Ps)
}
func (d *Dao) tasklist(c context.Context, ltp string, bizID, flowID, UID int64, pn, ps int) (ids []int64, count int64, err error) {
db := d.orm.Table("task").Where("business_id=? AND flow_id=?", bizID, flowID)
switch ltp {
case "seized":
db = db.Where("state=?", task.TaskStateDispatch)
case "delayd":
db = db.Where("state=?", task.TaskStateDelay)
case "assignd":
db = db.Where("state=? AND admin_id>0", task.TaskStateDispatch)
}
if UID > 0 {
db = db.Where("uid=?", UID)
}
var rows *sql.Rows
rows, err = db.Count(&count).Select("id").Order("weight DESC").Offset((pn - 1) * ps).Limit(ps).Rows()
if err != nil {
log.Error("tasklist error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var id int64
if err = rows.Scan(&id); err != nil {
log.Error("tasklist error(%v)", err)
return
}
ids = append(ids, id)
}
return
}
//TaskHitAuditing 检查资源是否正在审核
func (d *Dao) TaskHitAuditing(c context.Context, rids []int64) (map[int64]struct{}, error) {
hitids := make(map[int64]struct{})
rows, err := d.orm.Table("task").Select("rid").Where("rid IN (?)", rids).
Where("state = ? AND gtime!=0", task.TaskStateDispatch).Rows()
if err != nil {
return hitids, err
}
defer rows.Close()
for rows.Next() {
var id int64
if err = rows.Scan(&id); err != nil {
return hitids, err
}
hitids[id] = struct{}{}
}
return hitids, err
}

View File

@@ -0,0 +1,64 @@
package gorm
import (
"context"
taskmod "go-common/app/admin/main/aegis/model/task"
"go-common/library/log"
)
// AddConfig add config
func (d *Dao) AddConfig(c context.Context, config *taskmod.Config, confJSON interface{}) (err error) {
if config.ConfType == taskmod.TaskConfigRangeWeight { //粉丝数,等待时长,分组权重配置去重
name := "%" + confJSON.(*taskmod.RangeWeightConfig).Name + "%"
err = d.orm.Table("task_config").Where("business_id=? AND flow_id=? AND conf_type=? AND conf_json LIKE ?", config.BusinessID, config.FlowID, taskmod.TaskConfigRangeWeight, name).
Assign(map[string]interface{}{
"conf_json": config.ConfJSON,
"btime": config.Btime,
"etime": config.Etime,
"uid": config.UID,
"uname": config.Uname,
"description": config.Description,
}).FirstOrCreate(config).Error
return err
}
return d.orm.Create(config).Error
}
// UpdateConfig update config
func (d *Dao) UpdateConfig(c context.Context, config *taskmod.Config) (err error) {
return d.orm.Model(&taskmod.Config{}).Where("id=?", config.ID).Update(config).Error
}
// SetStateConfig update config
func (d *Dao) SetStateConfig(c context.Context, id int64, state int8) (err error) {
return d.orm.Model(&taskmod.Config{}).Where("id=?", id).Update("state", state).Error
}
// QueryConfigs list config
func (d *Dao) QueryConfigs(c context.Context, queryParams *taskmod.QueryParams) (configs []*taskmod.Config, count int64, err error) {
db := d.orm.Model(&taskmod.Config{}).Where("conf_type=?", queryParams.ConfType).Where("state=?", queryParams.State)
if queryParams.BusinessID > 0 {
db = db.Where("business_id=?", queryParams.BusinessID)
}
if queryParams.FlowID > 0 {
db = db.Where("flow_id=?", queryParams.FlowID)
}
if len(queryParams.Btime) > 0 && len(queryParams.Etime) > 0 {
db = db.Where("mtime>=? AND mtime<=?", queryParams.Btime, queryParams.Etime)
}
if len(queryParams.ConfName) > 0 {
db = db.Where("conf_json LIKE '%" + queryParams.ConfName + "%'")
}
if err = db.Count(&count).Offset((queryParams.Pn - 1) * queryParams.Ps).Order("mtime DESC").Limit(queryParams.Ps).Find(&configs).Error; err != nil {
log.Error("query error(%v)", err)
return
}
return
}
// DeleteConfig delete config
func (d *Dao) DeleteConfig(c context.Context, id int64) (err error) {
return d.orm.Where("id=?", id).Delete(&taskmod.Config{}).Error
}

View File

@@ -0,0 +1,73 @@
package gorm
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/task"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoQueryConfigs(t *testing.T) {
convey.Convey("QueryConfigs", t, func(ctx convey.C) {
var (
c = context.Background()
params = &task.QueryParams{
BusinessID: 1,
FlowID: 1,
Btime: "0000-00-00 00:00:00",
Etime: "2018-12-12 12:12:12",
ConfName: "mid",
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, err := d.QueryConfigs(c, params)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDeleteConfig(t *testing.T) {
convey.Convey("DeleteConfig", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DeleteConfig(c, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetStateConfig(t *testing.T) {
convey.Convey("SetStateConfig", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SetStateConfig(c, 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpdateConfig(t *testing.T) {
convey.Convey("UpdateConfig", t, func(ctx convey.C) {
var (
config = &task.Config{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.UpdateConfig(cntx, config)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,155 @@
package gorm
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/common"
taskmod "go-common/app/admin/main/aegis/model/task"
"github.com/smartystreets/goconvey/convey"
)
func TestUndoStat(t *testing.T) {
convey.Convey("UndoStat", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UndoStat(c, 0, 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestTaskStat(t *testing.T) {
convey.Convey("TaskStat", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.TaskStat(c, 0, 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestTaskMaxWeight(t *testing.T) {
convey.Convey("MaxWeight", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.MaxWeight(c, 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTaskListSeized(t *testing.T) {
convey.Convey("TaskListSeized", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, _, err := d.TaskListSeized(c, &taskmod.ListOptions{})
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTxCloseTasks(t *testing.T) {
convey.Convey("TxCloseTasks", t, func(ctx convey.C) {
var (
c = context.Background()
tx, _ = d.BeginTx(c)
)
defer tx.Commit()
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.TxCloseTasks(tx, []int64{}, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTxSubmit(t *testing.T) {
convey.Convey("TxSubmit", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTx(cntx)
opt = &taskmod.SubmitOptions{}
)
defer tx.Commit()
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, err := d.TxSubmit(tx, opt, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestCloseTask(t *testing.T) {
convey.Convey("CloseTask", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.CloseTask(cntx, 0)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTaskByRID(t *testing.T) {
convey.Convey("TaskByRID", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, err := d.TaskByRID(cntx, 0, 1)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTaskListAssignd(t *testing.T) {
convey.Convey("TaskListAssignd", t, func(ctx convey.C) {
var (
opt = &taskmod.ListOptions{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, _, err := d.TaskListAssignd(cntx, opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestTaskListDelayd(t *testing.T) {
convey.Convey("TaskListDelayd", t, func(ctx convey.C) {
var (
opt = &taskmod.ListOptions{
BaseOptions: common.BaseOptions{
UID: 1,
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, _, err := d.TaskListDelayd(cntx, opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,126 @@
package gorm
import (
"context"
"strings"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
)
// TokenByID .
func (d *Dao) TokenByID(c context.Context, id int64) (t *net.Token, err error) {
t = &net.Token{}
err = d.orm.Where("id=?", id).First(t).Error
if err == gorm.ErrRecordNotFound {
err = ecode.AegisTokenNotFound
return
}
if err != nil {
log.Error("TokenByID(%+v) error(%v)", id, err)
}
return
}
// Tokens .
func (d *Dao) Tokens(c context.Context, ids []int64) (list []*net.Token, err error) {
list = []*net.Token{}
err = d.orm.Where("id in (?)", ids).Find(&list).Error
if err != nil {
log.Error("Tokens(%v) error(%v)", ids, err)
}
return
}
func (d *Dao) tokenListDB(netID []int64, id []int64, name string, onlyAssign bool) (db *gorm.DB) {
db = d.orm.Table(net.TableToken).Where("net_id in (?)", netID)
if len(id) > 0 {
db = db.Where("id in (?)", id)
}
name = strings.TrimSpace(name)
if name != "" {
db = db.Where("name=?", name)
}
if onlyAssign {
db = db.Where("compare=?", net.TokenCompareAssign)
}
return
}
// TokenListWithPager .
func (d *Dao) TokenListWithPager(c context.Context, pm *net.ListTokenParam) (result *net.ListTokenRes, err error) {
result = &net.ListTokenRes{
Pager: net.Pager{
Num: pm.Pn,
Size: pm.Ps,
},
}
db := d.tokenListDB([]int64{pm.NetID}, pm.ID, pm.Name, pm.Assign)
err = db.Count(&result.Pager.Total).Scopes(pager(pm.Ps, pm.Pn, pm.Sort)).Find(&result.Result).Error
if err != nil {
log.Error("TokenListWithPager find error(%v) params(%+v)", err, pm)
}
return
}
// TokenList .
func (d *Dao) TokenList(c context.Context, netID []int64, id []int64, name string, onlyAssign bool) (list []*net.Token, err error) {
err = d.tokenListDB(netID, id, name, onlyAssign).Find(&list).Error
if err != nil {
log.Error("TokenList find error(%v)", err)
}
return
}
// TokenByUnique .
func (d *Dao) TokenByUnique(c context.Context, netID int64, name string, compare int8, value string) (t *net.Token, err error) {
t = &net.Token{}
err = d.orm.Where("net_id=? AND name=? AND compare=? AND value=?", netID, name, compare, value).First(t).Error
if err == gorm.ErrRecordNotFound {
err = nil
t = nil
return
}
if err != nil {
log.Error("TokenByUnique(%d,%s,%d,%s) error(%v)", netID, name, compare, value, err)
}
return
}
// TokenBinds .
func (d *Dao) TokenBinds(c context.Context, id []int64) (t []*net.TokenBind, err error) {
t = []*net.TokenBind{}
err = d.orm.Where("id in (?)", id).Find(&t).Error
if err != nil {
log.Error("TokenBinds(%+v) error(%v)", id, err)
}
return
}
// TokenBindByElement .
func (d *Dao) TokenBindByElement(c context.Context, elementID []int64, tp []int8, onlyAvailable bool) (binds map[int64][]*net.TokenBind, err error) {
binds = map[int64][]*net.TokenBind{}
list := []*net.TokenBind{}
db := d.orm.Where("element_id in (?) AND type in (?)", elementID, tp)
if onlyAvailable {
db = db.Scopes(Available)
}
if err = db.Find(&list).Error; err != nil {
log.Error("TokenBindByElement error(%v) elementid(%d) type(%v) onlyavailable(%v)", err, elementID, tp, onlyAvailable)
return
}
for _, item := range list {
if _, exist := binds[item.ElementID]; !exist {
binds[item.ElementID] = []*net.TokenBind{item}
continue
}
binds[item.ElementID] = append(binds[item.ElementID], item)
}
return
}

View File

@@ -0,0 +1,81 @@
package gorm
import (
"go-common/app/admin/main/aegis/model/net"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTokens(t *testing.T) {
var (
ids = []int64{}
)
convey.Convey("Tokens", t, func(ctx convey.C) {
no, err := d.Tokens(cntx, ids)
ctx.Convey("Then err should be nil.no should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(no, convey.ShouldNotBeNil)
})
})
}
func TestDaoTokenList(t *testing.T) {
convey.Convey("TokenList", t, func(ctx convey.C) {
result, err := d.TokenList(cntx, []int64{1}, []int64{}, "1", true)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoTokenByID(t *testing.T) {
convey.Convey("TokenByID", t, func(ctx convey.C) {
d.TokenByID(cntx, 1)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
})
})
}
func TestDaoTokenListWithPager(t *testing.T) {
var (
pm = &net.ListTokenParam{}
)
convey.Convey("TokenListWithPager", t, func(ctx convey.C) {
result, err := d.TokenListWithPager(cntx, pm)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoTokenByUnique(t *testing.T) {
convey.Convey("TokenByUnique", t, func(ctx convey.C) {
_, err := d.TokenByUnique(cntx, 0, "", 0, "")
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTokenBinds(t *testing.T) {
convey.Convey("TokenBinds", t, func(ctx convey.C) {
result, err := d.TokenBinds(cntx, []int64{})
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoTokenBindByElement(t *testing.T) {
convey.Convey("TokenBindByElement", t, func(ctx convey.C) {
result, err := d.TokenBindByElement(cntx, []int64{}, []int8{}, true)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,118 @@
package gorm
import (
"context"
"strings"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
)
// TransitionByID .
func (d *Dao) TransitionByID(c context.Context, id int64) (n *net.Transition, err error) {
n = &net.Transition{}
err = d.orm.Where("id=?", id).First(n).Error
if err == gorm.ErrRecordNotFound {
err = ecode.AegisTranNotFound
return
}
if err != nil {
log.Error("TransitionByID(%d) error(%v)", id, err)
}
return
}
// Transitions .
func (d *Dao) Transitions(c context.Context, id []int64) (n []*net.Transition, err error) {
n = []*net.Transition{}
err = d.orm.Where("id in (?)", id).Find(&n).Error
if err != nil {
log.Error("Transitions(%v) error(%v)", id, err)
}
return
}
// TransitionList .
func (d *Dao) TransitionList(c context.Context, pm *net.ListNetElementParam) (result *net.ListTransitionRes, err error) {
result = &net.ListTransitionRes{
Pager: net.Pager{
Num: pm.Pn,
Size: pm.Ps,
},
}
db := d.orm.Table(net.TableTransition).Where("net_id=?", pm.NetID)
if len(pm.ID) > 0 {
db = db.Where("id in (?)", pm.ID)
}
pm.Name = strings.TrimSpace(pm.Name)
if pm.Name != "" {
db = db.Where("name=?", pm.Name)
}
err = db.Scopes(state(pm.State)).Count(&result.Pager.Total).Scopes(pager(pm.Ps, pm.Pn, pm.Sort)).Find(&result.Result).Error
if err != nil {
log.Error("TransitionList find error(%v) params(%+v)", err, pm)
}
return
}
// TransitionByUnique .
func (d *Dao) TransitionByUnique(c context.Context, netID int64, name string) (t *net.Transition, err error) {
t = &net.Transition{}
err = d.orm.Where("net_id=? AND name=?", netID, name).First(t).Error
if err == gorm.ErrRecordNotFound {
err = nil
t = nil
return
}
if err != nil {
log.Error("TransitionByUnique(%d,%s) error(%v)", netID, name, err)
}
return
}
// TransitionIDByNet .
func (d *Dao) TransitionIDByNet(c context.Context, netID []int64, onlyDispatch bool, onlyAvailable bool) (ids map[int64][]int64, err error) {
ids = map[int64][]int64{}
listi := []struct {
ID int64 `gorm:"column:id"`
NetID int64 `gorm:"column:net_id"`
}{}
db := d.orm.Table(net.TableTransition).Where("net_id in (?)", netID)
if onlyAvailable {
db = db.Scopes(Available)
}
if onlyDispatch {
db = db.Where("`limit`>0").Scopes(manual)
}
if err = db.Find(&listi).Error; err != nil {
log.Error("TransitionIDByNet netid(%v) error(%v)", netID, err)
return
}
for _, item := range listi {
ids[item.NetID] = append(ids[item.NetID], item.ID)
}
return
}
func manual(db *gorm.DB) *gorm.DB {
return db.Where("`trigger`=?", net.TriggerManual)
}
// TranByNet .
func (d *Dao) TranByNet(c context.Context, netID int64, onlyAvailable bool) (list []*net.Transition, err error) {
list = []*net.Transition{}
db := d.orm
if netID > 0 {
db = db.Where("net_id=?", netID)
}
if onlyAvailable {
db = db.Scopes(Available)
}
if err = db.Find(&list).Error; err != nil {
log.Error("TranByNet error(%v)", err)
}
return
}

View File

@@ -0,0 +1,83 @@
package gorm
import (
"go-common/app/admin/main/aegis/model/net"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var tt = &net.Transition{
ID: 1,
NetID: 1,
Trigger: net.TriggerManual,
Name: "first",
ChName: "第一次审核",
Description: "新建变迁",
UID: 421,
}
func TestDaoTransitionByID(t *testing.T) {
convey.Convey("TransitionByID", t, func(ctx convey.C) {
n, err := d.TransitionByID(cntx, tt.ID)
ctx.Convey("Then err should be nil.n should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(n, convey.ShouldNotBeNil)
})
})
}
func TestDaoTransitionList(t *testing.T) {
var (
pm = &net.ListNetElementParam{
NetID: 1,
Ps: 20,
ID: []int64{1},
Name: "1",
}
)
convey.Convey("TransitionList", t, func(ctx convey.C) {
result, err := d.TransitionList(cntx, pm)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoTransitions(t *testing.T) {
convey.Convey("TransitionList", t, func(ctx convey.C) {
_, err := d.Transitions(cntx, []int64{})
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTransitionByUnique(t *testing.T) {
convey.Convey("TransitionByUnique", t, func(ctx convey.C) {
_, err := d.TransitionByUnique(cntx, 0, "")
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTransitionIDByNet(t *testing.T) {
convey.Convey("TransitionIDByNet", t, func(ctx convey.C) {
a, err := d.TransitionIDByNet(cntx, []int64{1}, true, true)
t.Logf("a(%+v)", a)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTranByNet(t *testing.T) {
convey.Convey("TranByNet", t, func(ctx convey.C) {
_, err := d.TranByNet(cntx, 0, true)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,69 @@
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",
"filter_test.go",
"log_test.go",
"resource_test.go",
"role_test.go",
"search_test.go",
"upload_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"filter.go",
"log.go",
"resource.go",
"role.go",
"search.go",
"upload.go",
],
importpath = "go-common/app/admin/main/aegis/dao/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//library/database/elastic:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr: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,41 @@
package http
import (
"context"
"go-common/app/admin/main/aegis/conf"
"go-common/library/database/elastic"
bm "go-common/library/net/http/blademaster"
)
// Dao dao
type Dao struct {
c *conf.Config
clientR, clientW *bm.Client
es *elastic.Elastic
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
clientR: bm.NewClient(c.HTTPClient.Read),
clientW: bm.NewClient(c.HTTPClient.Write),
es: elastic.NewElastic(&elastic.Config{
Host: c.Host.Manager,
HTTPClient: c.HTTPClient.Es,
}),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}

View File

@@ -0,0 +1,62 @@
package http
import (
"context"
"flag"
"os"
"strings"
"testing"
"go-common/app/admin/main/aegis/conf"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
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(err)
}
d = New(conf.Conf)
cntx = context.Background()
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
d.clientR.SetTransport(gock.DefaultTransport)
d.clientW.SetTransport(gock.DefaultTransport)
r.Method = strings.ToUpper(method)
return r
}
func TestHttpPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
ctx.Convey("Ping", func(ctx convey.C) {
err := d.Ping(cntx)
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,49 @@
package http
import (
"context"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_filterURI = "/x/internal/filter/v3/hit"
)
// Res 筛选结果
type Res struct {
Code int64 `json:"code"`
Data []struct {
Level int64 `json:"level"`
Msg string `json:"msg"`
} `json:"data"`
}
// FilterMulti .批量过滤
func (d *Dao) FilterMulti(c context.Context, area string, msg string) (hits []string, err error) {
params := url.Values{}
params.Set("area", area)
params.Set("msg", msg)
params.Set("level", "10")
res := new(Res)
log.Info("FilterMulti area(%s) msg(%s)", area, msg)
if err = d.clientR.Post(c, d.c.Host.API+_filterURI, "", params, res); err != nil {
log.Error("d.clientR.Get error(%v)", err)
return
}
if res.Code != 0 {
err = ecode.Code(res.Code)
log.Error("FilterMulti res(%+v) error(%+v)", res, err)
return
}
for _, dt := range res.Data {
hits = append(hits, dt.Msg)
}
log.Info("FilterMulti area(%s) msg(%s) hits(%v)", area, msg, hits)
return
}

View File

@@ -0,0 +1,43 @@
package http
import (
"context"
"reflect"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestHttpFilterMulti(t *testing.T) {
convey.Convey("FilterMulti", t, func(ctx convey.C) {
var (
c = context.Background()
area = ""
msg = ""
successRes = `{"code":0,"data":[{"level":10,"msg":"女装大佬"}]}`
failRes = `{"code":200,"data":[{"level":10,"msg":"女装大佬"}]}`
)
ctx.Convey("success", func(ctx convey.C) {
httpMock("POST", d.c.Host.API+_filterURI).Reply(200).JSON(successRes)
hits, err := d.FilterMulti(c, area, msg)
ctx.Convey("Then err should be nil.hits should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(reflect.DeepEqual(hits, []string{"女装大佬"}), convey.ShouldEqual, true)
})
})
ctx.Convey("request fail", func(ctx convey.C) {
httpMock("POST", d.c.Host.API+_filterURI).Reply(504)
_, err := d.FilterMulti(c, area, msg)
ctx.Convey("Then err should be nil.hits should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
ctx.Convey("business fail", func(ctx convey.C) {
httpMock("POST", d.c.Host.API+_filterURI).Reply(200).JSON(failRes)
_, err := d.FilterMulti(c, area, msg)
ctx.Convey("Then err should be nil.hits should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,182 @@
package http
import (
"context"
"fmt"
"reflect"
"strconv"
"strings"
"time"
"go-common/app/admin/main/aegis/model"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/xstr"
)
//const
const (
LogMinYear = 2018
LogMinTime = "2018-11-01 10:00:00"
)
func setESParams(r *elastic.Request, args interface{}, cm model.EsCommon) {
av := reflect.ValueOf(args)
if av.Kind() == reflect.Ptr {
av = av.Elem()
}
if av.Kind() != reflect.Struct {
return
}
atp := av.Type()
ranges := map[string]map[string]interface{}{}
for i := atp.NumField() - 1; i >= 0; i-- {
fdt := atp.Field(i)
tag := fdt.Tag.Get("reflect")
if tag == "ignore" || tag == "" {
continue
}
fdv := av.Field(i)
fdk := fdt.Type.Kind()
if (fdk == reflect.Slice || fdk == reflect.String) && fdv.Len() == 0 {
continue
}
//default处理
omitdefault := strings.Index(tag, ",omitdefault")
tag = strings.Replace(tag, ",omitdefault", "", -1)
fdvv := fdv.Interface()
fdvslice := false
if omitdefault > -1 && fmt.Sprintf("%v", fdvv) == fdt.Tag.Get("default") {
continue
}
//字段值处理parse额外处理
switch fdk {
case reflect.Int64, reflect.Int32, reflect.Int, reflect.Int16, reflect.Int8:
fdvv = fdv.Int()
case reflect.String:
if fdv.Len() == 0 {
continue
}
v := fdv.String()
parse := fdt.Tag.Get("parse")
if parse == "int" {
vi, err := strconv.ParseInt(v, 10, 64)
if err != nil {
log.Error("setESParams strconv.ParseInt(%s) error(%v)", v, err)
continue
}
fdvv = vi
} else if parse == "[]int" {
vi, err := xstr.SplitInts(v)
if err != nil {
log.Error("setESParams xstr.SplitInts(%s) error(%v)", v, err)
continue
}
fdvv = vi
fdvslice = true
} else {
fdvv = v
}
case reflect.Slice:
if fdv.Len() == 0 {
continue
}
fdvslice = true
default:
log.Warn("setESParams not support kind(%s) for tag(%s)", fdk.String(), tag)
continue
}
//范围处理
from := strings.Index(tag, ",from")
to := strings.Index(tag, ",to")
if from > -1 {
if _, exist := ranges[tag[:from]]; !exist {
ranges[tag[:from]] = map[string]interface{}{}
}
ranges[tag[:from]]["from"] = fdvv
continue
}
if to > -1 {
if _, exist := ranges[tag[:to]]; !exist {
ranges[tag[:to]] = map[string]interface{}{}
}
ranges[tag[:to]]["to"] = fdvv
continue
}
if fdvslice {
r.WhereIn(tag, fdvv)
} else {
r.WhereEq(tag, fdvv)
}
}
for field, items := range ranges {
r.WhereRange(field, items["from"], items["to"], elastic.RangeScopeLcRc)
}
r.Ps(cm.Ps).Pn(cm.Pn)
order := []map[string]string{}
if cm.Order != "" || cm.Sort != "" {
r.Order(cm.Order, cm.Sort)
order = append(order, map[string]string{cm.Order: cm.Sort})
}
if cm.Group != "" {
r.GroupBy(elastic.EnhancedModeDistinct, cm.Group, order)
}
}
//QueryLogSearch .
func (d *Dao) QueryLogSearch(c context.Context, args *model.ParamsQueryLog, cm model.EsCommon) (resp *model.SearchLogResult, err error) {
var (
min int = LogMinYear
max int
ctimefrom, ctimeto time.Time
)
//默认获取所有行为日志,确定了时间范围的,只查询该段范围内的日志
if args.CtimeFrom != "" {
ctimefrom, _ = time.ParseInLocation("2006-01-02 15:04:05", args.CtimeFrom, time.Local)
if ctimefrom.Year() > min {
min = ctimefrom.Year()
}
}
if args.CtimeTo != "" {
ctimeto, _ = time.ParseInLocation("2006-01-02 15:04:05", args.CtimeTo, time.Local)
if ctimeto.Year() >= min {
max = ctimeto.Year()
}
} else {
max = time.Now().Year()
}
tmpl := ",log_audit_%d_%d"
index := ""
for i := min; i <= max; i++ {
index += fmt.Sprintf(tmpl, args.Business, i)
}
index = strings.TrimLeft(index, ",")
r := d.es.NewRequest("log_audit").Index(index).Fields(
"uid",
"uname",
"oid",
"type",
"action",
"str_0",
"str_1",
"str_2",
"int_0",
"int_1",
"int_2",
"ctime",
"extra_data")
setESParams(r, args, cm)
err = r.Scan(c, &resp)
return
}

View File

@@ -0,0 +1,33 @@
package http
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model"
"github.com/smartystreets/goconvey/convey"
)
func TestHttpQueryLogSearch(t *testing.T) {
convey.Convey("QueryLogSearch", t, func(ctx convey.C) {
var (
c = context.Background()
args = &model.ParamsQueryLog{
Business: 231,
Int0From: "0",
Int1: []int64{0, 1},
Int2: []int64{0},
Str0: []string{"0"},
CtimeFrom: "2019-01-01 00:00:00",
}
escm = model.EsCommon{Ps: 10, Pn: 1, Order: "ctime", Sort: "desc"}
)
ctx.Convey("success", func(ctx convey.C) {
res, err := d.QueryLogSearch(c, args, escm)
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,39 @@
package http
import (
"context"
"fmt"
"net/url"
"go-common/app/admin/main/aegis/model"
"go-common/library/ecode"
"go-common/library/log"
)
// SyncResource 同步到业务方
func (d *Dao) SyncResource(c context.Context, act *model.Action, ropt map[string]interface{}) (code int, err error) {
params := url.Values{}
for k, v := range ropt {
params.Set(k, fmt.Sprint(v))
}
requestParams := fmt.Sprintf("%s?%s", act.URL, params.Encode())
log.Info("SyncResource url(%v) params(%s)", act.URL, params.Encode())
if d.c.Debug == "local" || d.c.Debug == "nobusiness" {
return
}
res := new(struct {
Code int `json:"code"`
Msg string `json:"msg"`
Message string `json:"message"`
})
err = d.clientW.Post(c, act.URL, "", params, res)
code = res.Code
if err != nil || res.Code != 0 {
log.Error("clientW.Post err(%v) response(%+v) request(%s)", err, res, requestParams)
err = ecode.Errorf(ecode.AegisBusinessSyncErr, "业务回调错误 request(%s) httperror(%v) response(%+v)", requestParams, err, res)
}
return
}

View File

@@ -0,0 +1,19 @@
package http
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model"
"github.com/smartystreets/goconvey/convey"
)
func TestSyncResource(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("SyncResource", t, func(ctx convey.C) {
d.SyncResource(c, &model.Action{}, map[string]interface{}{"state": 1})
})
}

View File

@@ -0,0 +1,159 @@
package http
import (
"context"
"net/url"
"strconv"
"go-common/app/admin/main/aegis/model/task"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_getUIDs = "/x/admin/manager/users/uids"
_getUname = "/x/admin/manager/users/unames"
_getUdepartment = "/x/admin/manager/users/udepts"
_getRole = "/x/admin/manager/internal/user/role"
_getRoles = "/x/admin/manager/internal/user/roles"
)
// GetRole 获取用户对应业务下的角色
func (d *Dao) GetRole(c context.Context, bid, uid int64) (roles []*task.Role, err error) {
roles = []*task.Role{}
params := url.Values{}
params.Set("bid", strconv.FormatInt(bid, 10))
params.Set("uid", strconv.FormatInt(uid, 10))
res := new(struct {
Code int `json:"code"`
Data []*task.Role `json:"data"`
})
if err = d.clientR.Get(c, d.c.Host.Manager+_getRole, "", params, res); err != nil {
log.Error("GetRole error(%v) url(%s) params(%s)", err, d.c.Host.Manager+_getRole, params.Encode())
return
}
if res.Code != 0 {
log.Error("GetRole request failed res(%+v) url(%s) params(%s)", res, d.c.Host.Manager+_getRole, params.Encode())
return
}
if len(res.Data) == 0 {
return
}
roles = res.Data
return
}
// GetUserRoles 获取用户在所有业务下的角色
func (d *Dao) GetUserRoles(c context.Context, uid int64) (roles []*task.Role, err error) {
roles = []*task.Role{}
params := url.Values{}
params.Set("uid", strconv.FormatInt(uid, 10))
res := new(struct {
Code int `json:"code"`
Data []*task.Role `json:"data"`
})
if err = d.clientR.Get(c, d.c.Host.Manager+_getRoles, "", params, res); err != nil {
log.Error("GetUserRoles error(%v) url(%s) params(%s)", err, d.c.Host.Manager+_getRole, params.Encode())
return
}
if res.Code != 0 {
log.Error("GetUserRoles request failed res(%+v) url(%s) params(%s)", res, d.c.Host.Manager+_getRole, params.Encode())
return
}
if len(res.Data) == 0 {
return
}
roles = res.Data
return
}
// GetUnames .
func (d *Dao) GetUnames(c context.Context, uids []int64) (unames map[int64]string, err error) {
unames = map[int64]string{}
if len(uids) == 0 {
return
}
params := url.Values{}
params.Set("uids", xstr.JoinInts(uids))
res := new(struct {
Code int `json:"code"`
Data map[int64]string `json:"data"`
})
if err = d.clientR.Get(c, d.c.Host.Manager+_getUname, "", params, res); err != nil {
log.Error("GetUnames error(%v) url(%s) params(%s)", err, d.c.Host.Manager+_getUname, params.Encode())
return
}
if res.Code != 0 {
log.Error("GetUnames request failed res(%+v) url(%s) params(%s)", res, d.c.Host.Manager+_getUname, params.Encode())
return
}
if len(res.Data) == 0 {
return
}
unames = res.Data
return
}
// GetUIDs .
func (d *Dao) GetUIDs(c context.Context, unames string) (uids map[string]int64, err error) {
uids = map[string]int64{}
params := url.Values{}
params.Set("unames", unames)
res := new(struct {
Code int `json:"code"`
Data map[string]int64 `json:"data"`
})
if err = d.clientR.Get(c, d.c.Host.Manager+_getUIDs, "", params, res); err != nil {
log.Error("GetUIDs error(%v) url(%s) params(%s)", err, d.c.Host.Manager+_getUname, params.Encode())
return
}
if res.Code != 0 {
log.Error("GetUIDs request failed res(%+v) url(%s) params(%s)", res, d.c.Host.Manager+_getUname, params.Encode())
return
}
if len(res.Data) == 0 {
return
}
uids = res.Data
return
}
// GetUdepartment .
func (d *Dao) GetUdepartment(c context.Context, uids []int64) (udepartment map[int64]string, err error) {
udepartment = map[int64]string{}
if len(uids) == 0 {
return
}
params := url.Values{}
params.Set("uids", xstr.JoinInts(uids))
res := new(struct {
Code int `json:"code"`
Data map[int64]string `json:"data"`
})
if err = d.clientR.Get(c, d.c.Host.Manager+_getUdepartment, "", params, res); err != nil {
log.Error("GetUdepartment error(%v) url(%s) params(%s)", err, d.c.Host.Manager+_getUdepartment, params.Encode())
return
}
if res.Code != 0 {
log.Error("GetUdepartment request failed res(%+v) url(%s) params(%s)", res, d.c.Host.Manager+_getUname, params.Encode())
return
}
if len(res.Data) == 0 {
return
}
udepartment = res.Data
return
}

View File

@@ -0,0 +1,75 @@
package http
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestHttpGetRole(t *testing.T) {
var (
c = context.TODO()
bid = int64(0)
uid = int64(0)
)
convey.Convey("GetRole", t, func(ctx convey.C) {
httpMock("GET", d.c.Host.Manager+_getRole).Reply(200).JSON(`{"code":0,"data":[{"id":0}]}`)
roles, err := d.GetRole(c, bid, uid)
ctx.Convey("Then err should be nil.roles should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(roles, convey.ShouldNotBeNil)
})
})
}
func TestHttpGetUserRoles(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("GetUserRoles", t, func(ctx convey.C) {
httpMock("GET", d.c.Host.Manager+_getRoles).Reply(200).JSON(`{"code":0,"data":[{"id":0}]}`)
roles, err := d.GetUserRoles(c, 421)
ctx.Convey("Then err should be nil.roles should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(roles, convey.ShouldNotBeNil)
})
})
}
func TestHttpGetUnames(t *testing.T) {
var (
c = context.TODO()
uids = []int64{421}
)
convey.Convey("GetUnames", t, func(ctx convey.C) {
httpMock("GET", d.c.Host.Manager+_getUname).Reply(200).JSON(`{"code":0,"data":{"421":"丝瓜"}}`)
unames, err := d.GetUnames(c, uids)
ctx.Convey("Then err should be nil.unames should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(unames, convey.ShouldNotBeNil)
})
})
}
func TestHttpGetUIDs(t *testing.T) {
convey.Convey("GetUIDs", t, func(ctx convey.C) {
httpMock("GET", d.c.Host.Manager+_getUIDs).Reply(200).JSON(`{"code":0,"data":{"cxf":481}}`)
uids, err := d.GetUIDs(cntx, "cxf")
ctx.Convey("Then err should be nil.unames should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(uids, convey.ShouldNotBeNil)
})
})
}
func TestHttpGetUdepartment(t *testing.T) {
convey.Convey("GetUdepartment", t, func(ctx convey.C) {
httpMock("GET", d.c.Host.Manager+_getUdepartment).Reply(200).JSON(`{"code":0,"data":{"481":"CTO"}}`)
depart, err := d.GetUdepartment(cntx, []int64{481})
ctx.Convey("Then err should be nil.unames should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(depart, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,120 @@
package http
import (
"context"
"encoding/json"
"net/url"
"strings"
"go-common/app/admin/main/aegis/model"
"go-common/library/database/elastic"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_upsertES = "/x/admin/search/upsert"
)
// ResourceES search archives by es.
func (d *Dao) ResourceES(c context.Context, arg *model.SearchParams) (sres *model.SearchRes, err error) {
r := d.es.NewRequest("aegis_resource").Index("aegis_resource").Fields(
"id",
"business_id",
"flow_id",
"oid",
"mid",
"content",
"extra1",
"extra2",
"extra3",
"extra4",
"extra5",
"extra6",
"extra1s",
"extra2s",
"extra3s",
"extra4s",
"extratime1",
"octime",
"ptime",
"metadata",
"note",
"reject_reason",
"reason_id",
"state",
"ctime",
).OrderScoreFirst(false)
escm := model.EsCommon{
Ps: arg.Ps,
Pn: arg.Pn,
Order: "ctime",
Sort: strings.ToLower(arg.CtimeOrder),
}
if escm.Sort != "asc" && escm.Sort != "desc" {
escm.Sort = "desc"
}
setESParams(r, arg, escm)
if arg.KeyWord != "" { //描述
arg.KeyWord = strings.Replace(arg.KeyWord, "", ",", -1)
r.WhereLike([]string{"content"}, strings.Split(arg.KeyWord, ","), true, elastic.LikeLevelHigh)
}
log.Info("ResourceES params(%s)", r.Params())
sres = &model.SearchRes{}
if err = r.Scan(c, sres); err != nil {
log.Error("ResourceES r.Scan params(%s)|error(%v)", r.Params(), err)
return
}
arg.Pn = sres.Page.Num
arg.Ps = sres.Page.Size
arg.Total = sres.Page.Total
return
}
//UpsertES 更新搜索
func (d *Dao) UpsertES(c context.Context, rsc []*model.UpsertItem) (err error) {
if len(rsc) == 0 {
return
}
items := []*model.UpsertItem{}
for _, item := range rsc {
if item == nil || item.ID <= 0 {
continue
}
items = append(items, item)
}
data := map[string][]*model.UpsertItem{
"aegis_resource": items,
}
datab, err := json.Marshal(data)
if err != nil {
log.Error("UpsertES json.Marshal error(%v) resource(%+v)", err, rsc)
return err
}
res := new(struct {
Code int `json:"code"`
Message string `json:"message"`
})
params := url.Values{}
params.Set("business", "aegis_resource")
params.Set("insert", "false")
params.Set("data", string(datab))
if err = d.clientW.Post(c, d.c.Host.Manager+_upsertES, "", params, res); err != nil {
log.Error("UpsertES d.clientW.Post error(%v) params(%+v)", err, params)
return
}
if res.Code != ecode.OK.Code() {
log.Error("UpsertES d.clientW.Post failed, response(%+v) params(%+v)", res, params)
return
}
log.Info("response(%+v) url=%s%s?%s", res, d.c.Host.Manager, _upsertES, params.Encode())
return
}

View File

@@ -0,0 +1,58 @@
package http
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model"
)
var arg = &model.SearchParams{
BusinessID: 1,
//CtimeFrom: "2018-01-01 01:01:01",
//CtimeTo: "2019-11-11 11:11:11",
OID: []string{"206137981869783258", "206137981871880409", "206129056929839317", "206117679558326449"},
KeyWord: "分享图片",
FlowID: -12345,
Extra1: "1,2,3,4,5",
Mid: -12345,
State: 0,
}
func TestHttpResourceES(t *testing.T) {
convey.Convey("ResourceES", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ResourceES(c, arg)
t.Logf("res(%+v)", res)
ctx.Convey("Then err should be nil.sres should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestUpsertES(t *testing.T) {
convey.Convey("UpsertES", t, func(ctx convey.C) {
rsc := []*model.UpsertItem{
{
ID: 47,
State: -3,
},
nil,
{
State: 0,
},
}
ctx.Convey("When everything goes positive", func(ctx convey.C) {
httpMock("POST", d.c.Host.Manager+_upsertES).Reply(200).JSON(`{"code":0,"message":"msg"}`)
err := d.UpsertES(context.Background(), rsc)
ctx.Convey("No return values", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,86 @@
package http
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"net/http"
"strconv"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
// bfs info
const (
_uploadURL = "/bfs/%s/%s"
_template = "%s\n%s\n%s\n%d\n"
_method = "PUT"
_bucket = "creative"
)
// Upload upload picture or log file to bfs
func (d *Dao) Upload(c context.Context, fileName string, fileType string, timing int64, data []byte) (location string, err error) {
var (
req *http.Request
resp *http.Response
code int
client = &http.Client{Timeout: time.Duration(d.c.Bfs.Timeout) * time.Millisecond}
url = fmt.Sprintf(d.c.Bfs.Host+_uploadURL, _bucket, fileName)
)
// prepare the data of the file and init the request
buf := new(bytes.Buffer)
_, err = buf.Write(data)
if err != nil {
log.Error("Upload.buf.Write.error(%v)", err)
err = ecode.RequestErr
return
}
if req, err = http.NewRequest(_method, url, buf); err != nil {
log.Error("http.NewRequest() Upload(%v) error(%v)", url, err)
return
}
// request setting
authorization := authorize(d.c.Bfs.Key, d.c.Bfs.Secret, _method, _bucket, fileName, timing)
req.Header.Set("Date", fmt.Sprint(timing))
req.Header.Set("Authorization", authorization)
req.Header.Set("Content-Type", fileType)
resp, err = client.Do(req)
// response treatment
if err != nil {
log.Error("Bfs client.Do(%s) error(%v)", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("Bfs status code error:%v", resp.StatusCode)
return
}
code, err = strconv.Atoi(resp.Header.Get("code"))
if err != nil || code != 200 {
err = fmt.Errorf("Bfs response code error:%v", code)
return
}
location = resp.Header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(_template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,41 @@
package http
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestHttpauthorize(t *testing.T) {
convey.Convey("authorize", t, func(ctx convey.C) {
var (
key = ""
secret = ""
method = ""
bucket = ""
file = ""
expire = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
authorization := authorize(key, secret, method, bucket, file, expire)
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(authorization, convey.ShouldNotBeNil)
})
})
})
}
func TestHttpUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.TODO()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, err := d.Upload(c, "", "", 0, []byte{})
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,54 @@
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",
"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",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"task.go",
],
importpath = "go-common/app/admin/main/aegis/dao/mc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model/common:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/log: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,36 @@
package mc
import (
"context"
"go-common/app/admin/main/aegis/conf"
"go-common/library/cache/memcache"
)
// Dao dao
type Dao struct {
c *conf.Config
mc *memcache.Pool
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
mc: memcache.NewPool(c.Memcache),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.mc.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}

View File

@@ -0,0 +1,39 @@
package mc
import (
"context"
"flag"
"fmt"
"os"
"testing"
"go-common/app/admin/main/aegis/conf"
)
var (
d *Dao
ctx 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)
ctx = context.TODO()
os.Exit(m.Run())
}

View File

@@ -0,0 +1,135 @@
package mc
import (
"context"
"encoding/json"
"fmt"
"go-common/app/admin/main/aegis/model/common"
gmc "go-common/library/cache/memcache"
"go-common/library/log"
)
// ConsumerOn 登入
func (d *Dao) ConsumerOn(c context.Context, opt *common.BaseOptions) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcKey(opt)
if err = conn.Set(&gmc.Item{Key: key, Value: []byte{1}, Expiration: d.c.Consumer.OnExp}); err != nil {
log.Error("conn.Set error(%v)", err)
}
return
}
// ConsumerOff .
func (d *Dao) ConsumerOff(c context.Context, opt *common.BaseOptions) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcKey(opt)
if err = conn.Delete(key); err != nil {
if err != gmc.ErrNotFound {
log.Error("conn.Delete error(%v)", err)
}
err = nil
}
return
}
// IsConsumerOn .
func (d *Dao) IsConsumerOn(c context.Context, opt *common.BaseOptions) (isOn bool, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcKey(opt)
if _, err = conn.Get(key); err != nil {
if err == gmc.ErrNotFound {
err = nil
} else {
log.Error("IsConsumerOn error(%v)", err)
}
return
}
isOn = true
if err = conn.Set(&gmc.Item{Key: key, Value: []byte{1}, Expiration: d.c.Consumer.OnExp}); err != nil {
log.Error("conn.Set error(%v)", err)
}
return
}
func mcKey(opt *common.BaseOptions) string {
return fmt.Sprintf("aegis%d_%d_%d", opt.BusinessID, opt.FlowID, opt.UID)
}
func roleKey(opt *common.BaseOptions) string {
return fmt.Sprintf("aegis_role%d_%d_%d", opt.BusinessID, opt.FlowID, opt.UID)
}
// Role .
type Role struct {
Role int8 `json:"role"`
Uname string `json:"uname"`
}
// GetRole TODO 目前缓存组长组员,以后扩展到存管理员
func (d *Dao) GetRole(c context.Context, opt *common.BaseOptions) (role int8, uname string, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := roleKey(opt)
var item *gmc.Item
if item, err = conn.Get(key); err != nil {
if err == gmc.ErrNotFound {
log.Info("GetRole opt(%+v) miss", opt)
err = nil
} else {
log.Error("GetRole opt(%+v) error(%v)", opt, err)
}
return
}
rt := new(Role)
if err = json.Unmarshal(item.Value, rt); err != nil {
log.Error("GetRole value(%s) error(%v)", string(item.Value), err)
return
}
role = rt.Role
uname = rt.Uname
return
}
// SetRole .
func (d *Dao) SetRole(c context.Context, opt *common.BaseOptions, role int8) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := roleKey(opt)
val := &Role{
Role: role,
Uname: opt.Uname,
}
var roleb []byte
if roleb, err = json.Marshal(val); err != nil {
log.Error("SetRole error(%v)", err)
return
}
if err = conn.Set(&gmc.Item{Key: key, Value: roleb, Expiration: d.c.Consumer.RoleExp}); err != nil {
log.Error("conn.Set error(%v)", err)
}
return
}
//DelRole .
func (d *Dao) DelRole(c context.Context, bizid, flowid int64, uids []int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for _, uid := range uids {
key := roleKey(&common.BaseOptions{
BusinessID: bizid,
FlowID: flowid,
UID: uid})
conn.Delete(key)
}
return
}

View File

@@ -0,0 +1,110 @@
package mc
import (
"context"
"testing"
"go-common/app/admin/main/aegis/model/common"
"github.com/smartystreets/goconvey/convey"
)
func TestMcConsumerOn(t *testing.T) {
convey.Convey("ConsumerOn", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ConsumerOn(context.TODO(), opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcConsumerOff(t *testing.T) {
convey.Convey("ConsumerOff", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ConsumerOff(context.TODO(), opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcIsConsumerOn(t *testing.T) {
convey.Convey("IsConsumerOn", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.IsConsumerOn(context.TODO(), opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcmcKey(t *testing.T) {
convey.Convey("mcKey", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := mcKey(opt)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcroleKey(t *testing.T) {
convey.Convey("roleKey", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := roleKey(opt)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcSetRole(t *testing.T) {
convey.Convey("SetRole", t, func(ctx convey.C) {
var (
c = context.TODO()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetRole(c, opt, 0)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcGetRole(t *testing.T) {
convey.Convey("GetRole", t, func(ctx convey.C) {
var (
c = context.TODO()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, _, err := d.GetRole(c, opt)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,61 @@
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",
"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 = [
"dao.go",
"monitor.go",
"task.go",
],
importpath = "go-common/app/admin/main/aegis/dao/mysql",
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/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/xstr: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,35 @@
package mysql
import (
"context"
"go-common/app/admin/main/aegis/conf"
xsql "go-common/library/database/sql"
)
// Dao dao
type Dao struct {
c *conf.Config
db *xsql.DB
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
db: xsql.NewMySQL(c.MySQL),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,52 @@
package mysql
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 TestMysqlPing(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,61 @@
package mysql
import (
"context"
"encoding/json"
"go-common/app/admin/main/aegis/model/monitor"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_moniBizRulesSql = "SELECT id,type,bid,name,state,stime,etime,rule,uid,ctime,mtime FROM monitor_rule WHERE bid = ?"
_moniRuleSql = "SELECT id,type,bid,name,state,stime,etime,rule,uid,ctime,mtime FROM monitor_rule WHERE id = ?"
)
// MoniBizRules 获取监控业务的所有配置
func (d *Dao) MoniBizRules(c context.Context, bid int64) (rules []*monitor.Rule, err error) {
var (
rows *xsql.Rows
)
if rows, err = d.db.Query(c, _moniBizRulesSql, bid); err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
rule := &monitor.Rule{}
var confStr string
if err = rows.Scan(&rule.ID, &rule.Type, &rule.BID, &rule.Name, &rule.State, &rule.STime, &rule.ETime, &confStr, &rule.UID, &rule.CTime, &rule.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
conf := &monitor.RuleConf{}
if err = json.Unmarshal([]byte(confStr), conf); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", confStr, err)
return
}
rule.RuleConf = conf
rules = append(rules, rule)
}
return
}
// MoniRule 根据id获取监控规则
func (d *Dao) MoniRule(c context.Context, rid int64) (rule *monitor.Rule, err error) {
rule = &monitor.Rule{}
var confStr string
row := d.db.QueryRow(c, _moniRuleSql, rid)
if err = row.Scan(&rule.ID, &rule.Type, &rule.BID, &rule.Name, &rule.State, &rule.STime, &rule.ETime, &confStr, &rule.UID, &rule.CTime, &rule.MTime); err != nil {
rule = nil
log.Error("row.Scan error(%v)", err)
return
}
conf := &monitor.RuleConf{}
if err = json.Unmarshal([]byte(confStr), conf); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", confStr, err)
return
}
rule.RuleConf = conf
return
}

View File

@@ -0,0 +1,38 @@
package mysql
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMysqlMoniBizRules(t *testing.T) {
convey.Convey("MoniBizRules", t, func(convCtx convey.C) {
var (
c = context.Background()
bid = int64(2)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
_, err := d.MoniBizRules(c, bid)
convCtx.Convey("Then err should be nil.rules should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlMoniRule(t *testing.T) {
convey.Convey("MoniRule", t, func(convCtx convey.C) {
var (
c = context.Background()
id = int64(1)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
_, err := d.MoniRule(c, id)
convCtx.Convey("Then err should be nil.rules should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,494 @@
package mysql
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"go-common/app/admin/main/aegis/model/common"
modtask "go-common/app/admin/main/aegis/model/task"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
"github.com/pkg/errors"
)
const (
_taskSQL = "SELECT id,business_id,flow_id,rid,admin_id,uid,state,weight,utime,gtime,mid,fans,`group`,reason,ctime,mtime from task WHERE id=?"
_listCheckSQL = "SELECT id FROM task WHERE id IN (%s)"
_dispatchByIDSQL = "UPDATE task SET gtime=? WHERE id=? AND state=? AND uid=? AND gtime=0"
_queryGtimeSQL = "SELECT gtime FROM task WHERE id=? AND state=? AND uid=?"
_dispatchSQL = "UPDATE task SET gtime=? WHERE state=? AND uid=? AND gtime='0000-00-00 00:00:00' ORDER BY weight LIMIT ?"
_releaseSQL = "UPDATE task SET admin_id=0,uid=0,state=0,gtime='0000-00-00 00:00:00' WHERE business_id=? AND flow_id=? AND uid=? AND (state=? OR (state=0 AND admin_id>0))"
_resetGtimeSQL = "UPDATE task SET gtime='0000-00-00 00:00:00' WHERE state=? AND business_id=? AND flow_id=? AND uid=?"
_seizeSQL = "UPDATE task SET state=?,uid=? WHERE id=? AND state=?"
_submitSQL = "UPDATE task SET state=?,uid=?,utime=? WHERE id=? AND state=? AND uid=?"
_delaySQL = "UPDATE task SET state=?,uid=?,reason=?,gtime='0000-00-00 00:00:00' WHERE id=? AND state=? AND uid=?"
_consumerSQL = "INSERT INTO task_consumer (business_id,flow_id,uid,state) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE state=?"
_onlinesSQL = "SELECT uid,mtime FROM task_consumer WHERE business_id=? AND flow_id=? AND state=?"
_isconsumerOnSQL = "SELECT state FROM task_consumer WHERE business_id=? AND flow_id=? AND uid=?"
_queryTaskSQL = "SELECT id,business_id,flow_id,uid,weight FROM task WHERE state=? AND mtime<=? AND id>? ORDER BY id LIMIT ?"
_countPersonalSQL = "SELECT count(*) FROM task WHERE state=? AND business_id=? AND flow_id=? AND uid=?"
_queryForSeizeSQL = "SELECT id FROM task WHERE state=? AND business_id=? AND flow_id=? AND uid IN (0,?) ORDER BY weight DESC LIMIT ?"
_listTasksSQL = "SELECT `id`,`business_id`,`flow_id`,`rid`,`admin_id`,`uid`,`state`,`weight`,`utime`,`gtime`,`mid`,`fans`,`group`,`reason`,`ctime`,`mtime` FROM task %s ORDER BY weight DESC LIMIT ?,?"
)
// TaskFromDB .
func (d *Dao) TaskFromDB(c context.Context, id int64) (task *modtask.Task, err error) {
task = &modtask.Task{}
err = d.db.QueryRow(c, _taskSQL, id).
Scan(&task.ID, &task.BusinessID, &task.FlowID, &task.RID, &task.AdminID, &task.UID, &task.State,
&task.Weight, &task.Utime, &task.Gtime, &task.MID, &task.Fans, &task.Group, &task.Reason, &task.Ctime, &task.Mtime)
if err != nil {
task = nil
if err == sql.ErrNoRows {
log.Error("TaskFromDB(%d) norows", id)
err = nil
return
}
log.Error("TaskFromDB(%d) error(%v)", id, errors.WithStack(err))
}
return
}
// DispatchByID 派遣任务,更新gtime
func (d *Dao) DispatchByID(c context.Context, mtasks map[int64]*modtask.Task, ids []int64, args ...interface{}) (missids map[int64]struct{}, err error) {
var (
gtime = time.Now()
uid = args[0].(int64)
)
missids = make(map[int64]struct{})
for _, id := range ids {
var (
rows int64
gt time.Time
res sql.Result
)
if err = d.db.QueryRow(c, _queryGtimeSQL, id, modtask.TaskStateDispatch, uid).Scan(&gt); err != nil {
if err == sql.ErrNoRows {
missids[id] = struct{}{}
err = nil
continue
}
log.Error("d.db.QueryRow error(%v)", errors.WithStack(err))
return
}
if gt.IsZero() {
res, err = d.db.Exec(c, _dispatchByIDSQL, gtime, id, modtask.TaskStateDispatch, uid)
if err != nil {
log.Error("Exec error(%v)", errors.WithStack(err))
return
}
if rows, err = res.RowsAffected(); err != nil {
log.Error("RowsAffected error(%v)", errors.WithStack(err))
return
}
if rows == 0 {
missids[id] = struct{}{}
} else {
mtasks[id].Gtime = common.IntTime(gtime.Unix())
}
} else {
mtasks[id].Gtime = common.IntTime(gt.Unix())
}
}
return
}
// DBDispatch 直接数据库派遣
func (d *Dao) DBDispatch(c context.Context, opt *modtask.NextOptions) (tasks []*modtask.Task, count int64, err error) {
var (
res sql.Result
gtime = time.Now()
)
// 1.直接更新派遣时间
res, err = d.db.Exec(c, _dispatchSQL, gtime, modtask.TaskStateDispatch, opt.UID, opt.DispatchCount)
if err != nil {
log.Error("Exec error(%v)", errors.WithStack(err))
return
}
if count, err = res.RowsAffected(); err != nil {
log.Error("RowsAffected error(%v)", errors.WithStack(err))
return
}
// 2.读取任务
wherecache := fmt.Sprintf("WHERE state=%d AND uid=%d AND gtime!='0000-00-00 00:00:00'", modtask.TaskStateDispatch, opt.UID)
return d.listTasks(c, &modtask.ListOptions{BaseOptions: opt.BaseOptions, Pager: common.Pager{Pn: 1, Ps: int(opt.DispatchCount)}}, wherecache)
}
// Release 释放任务
func (d *Dao) Release(c context.Context, opt *common.BaseOptions, delay bool) (rows int64, err error) {
sql := _releaseSQL
if delay {
sql = _releaseSQL + " AND gtime='0000-00-00 00:00:00'"
}
log.Info("Mysql Release(%+v) delay(%v)", opt, delay)
res, err := d.db.Exec(c, sql, opt.BusinessID, opt.FlowID, opt.UID, modtask.TaskStateDispatch)
if err != nil {
log.Error("db.Exec(%s)[%d,%d,%d,%d] error(%v)", sql, opt.BusinessID, opt.FlowID, opt.UID, modtask.TaskStateDispatch, err)
return
}
// 已经下发的延迟5分钟释放
if delay {
_, err = d.db.Exec(c, _resetGtimeSQL, modtask.TaskStateDispatch, opt.BusinessID, opt.FlowID, opt.UID)
if err != nil {
log.Error("db.Exec(%s)[%d,%d,%d,%d] error(%v)", sql, modtask.TaskStateDispatch, opt.BusinessID, opt.FlowID, opt.UID, err)
}
time.AfterFunc(5*time.Minute, func() {
d.Release(context.Background(), opt, false)
})
}
return res.RowsAffected()
}
// Seize 抢占任务
func (d *Dao) Seize(c context.Context, mapids map[int64]int64) (count int64, err error) {
tx, err := d.db.Begin(c)
if err != nil {
log.Error("d.Seize.Begin error(%v)", errors.WithStack(err))
return
}
defer tx.Commit()
for tid, uid := range mapids {
var (
rows int64
res sql.Result
)
res, err = tx.Exec(_seizeSQL, modtask.TaskStateDispatch, uid, tid, modtask.TaskStateInit)
if err != nil {
log.Error("Exec error(%v)", errors.WithStack(err))
tx.Rollback()
return
}
if rows, err = res.RowsAffected(); err != nil {
log.Error("RowsAffected error(%v)", errors.WithStack(err))
tx.Rollback()
return
}
if rows == 1 {
count++
}
}
return
}
// Delay 延迟任务
func (d *Dao) Delay(c context.Context, opt *modtask.DelayOptions) (rows int64, err error) {
var (
res sql.Result
)
res, err = d.db.Exec(c, _delaySQL, modtask.TaskStateDelay, opt.UID, opt.Reason, opt.TaskID, modtask.TaskStateDispatch, opt.UID)
if err != nil {
log.Error("Exec error(%v)", errors.WithStack(err))
return
}
if rows, err = res.RowsAffected(); err != nil {
log.Error("RowsAffected error(%v)", errors.WithStack(err))
return
}
return
}
// ListCheckUnSeized .
func (d *Dao) ListCheckUnSeized(c context.Context, mtasks map[int64]*modtask.Task, ids []int64, args ...interface{}) (missids map[int64]struct{}, err error) {
wherecase := fmt.Sprintf("state = %d", modtask.TaskStateInit)
return d.listCheck(c, wherecase, ids)
}
// ListCheckSeized .
func (d *Dao) ListCheckSeized(c context.Context, mtasks map[int64]*modtask.Task, ids []int64, args ...interface{}) (missids map[int64]struct{}, err error) {
if len(args) < 1 {
return
}
uid := args[0].(int64)
wherecase := fmt.Sprintf("state = %d", modtask.TaskStateDispatch)
if uid != 0 {
wherecase += fmt.Sprintf(" AND uid=%d", uid)
}
return d.listCheck(c, wherecase, ids)
}
// ListCheckDelay .
func (d *Dao) ListCheckDelay(c context.Context, mtasks map[int64]*modtask.Task, ids []int64, args ...interface{}) (missids map[int64]struct{}, err error) {
if len(args) < 1 {
return
}
uid := args[0].(int64)
wherecase := fmt.Sprintf("state=%d", modtask.TaskStateDelay)
if uid != 0 {
wherecase += fmt.Sprintf(" AND uid=%d", uid)
}
return d.listCheck(c, wherecase, ids)
}
// ListTasks .
func (d *Dao) ListTasks(c context.Context, opt *modtask.ListOptions) (tasks []*modtask.Task, count int64, err error) {
var (
wherecase string
cases []string
state int8
isDefault bool
)
switch opt.State {
case 1:
state = modtask.TaskStateInit
case 2:
state = modtask.TaskStateDispatch
case 3:
state = modtask.TaskStateDelay
case 4:
state = modtask.TaskStateDispatch
cases = append(cases, "admin_id>0")
default:
isDefault = true
cases = append(cases, fmt.Sprintf("state<%d", modtask.TaskStateSubmit))
}
if !isDefault {
cases = append(cases, fmt.Sprintf("state=%d", state))
if !opt.BisLeader && (opt.State == 2 || opt.State == 3 || opt.State == 4) {
cases = append(cases, fmt.Sprintf("uid=%d", opt.UID))
}
}
wherecase = fmt.Sprintf("WHERE business_id=%d AND flow_id=%d AND ", opt.BusinessID, opt.FlowID) + strings.Join(cases, " AND ")
return d.listTasks(c, opt, wherecase)
}
func (d *Dao) listTasks(c context.Context, opt *modtask.ListOptions, wherecase string) (tasks []*modtask.Task, count int64, err error) {
countSQL := fmt.Sprintf("SELECT count(*) FROM task %s", wherecase)
if err = d.db.QueryRow(c, countSQL).Scan(&count); err != nil {
log.Error("QueryRow error(%v)", err)
return
}
if count > 0 {
var (
rows *xsql.Rows
listSQL = fmt.Sprintf(_listTasksSQL, wherecase)
)
if rows, err = d.db.Query(c, listSQL, (opt.Pn-1)*opt.Ps, opt.Pn*opt.Ps); err != nil {
log.Error("Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
task := &modtask.Task{}
if err = rows.Scan(&task.ID, &task.BusinessID, &task.FlowID, &task.RID, &task.AdminID, &task.UID, &task.State,
&task.Weight, &task.Utime, &task.Gtime, &task.MID, &task.Fans, &task.Group, &task.Reason, &task.Ctime, &task.Mtime); err != nil {
log.Error("Scan error(%v)", err)
return
}
tasks = append(tasks, task)
}
}
return
}
func (d *Dao) listCheck(c context.Context, wherecase string, ids []int64) (missids map[int64]struct{}, err error) {
if len(ids) == 0 {
return
}
missids = make(map[int64]struct{})
mapids := make(map[int64]struct{})
log.Info("listCheck ids(%v)", ids)
defer func() {
log.Info("listCheck missids(%v)", missids)
}()
for _, id := range ids {
mapids[id] = struct{}{}
}
var (
rows *xsql.Rows
sqlstring = fmt.Sprintf(_listCheckSQL, xstr.JoinInts(ids)) + " AND " + wherecase
)
if rows, err = d.db.Query(c, sqlstring); err != nil {
log.Error("db.Query(%s) error(%v)", sqlstring, errors.WithStack(err))
return
}
defer rows.Close()
for rows.Next() {
var id int64
if err = rows.Scan(&id); err != nil {
log.Error("rows.Scan error(%v)", errors.WithStack(err))
return
}
delete(mapids, id)
}
for id := range mapids {
missids[id] = struct{}{}
}
return
}
// ConsumerOn .
func (d *Dao) ConsumerOn(c context.Context, opt *common.BaseOptions) (err error) {
return d.consumer(c, opt, modtask.ActionConsumerOn)
}
// ConsumerOff .
func (d *Dao) ConsumerOff(c context.Context, opt *common.BaseOptions) (err error) {
return d.consumer(c, opt, modtask.ActionConsumerOff)
}
// IsConsumerOn .
func (d *Dao) IsConsumerOn(c context.Context, opt *common.BaseOptions) (on bool, err error) {
var state int8
if err = d.db.QueryRow(c, _isconsumerOnSQL, opt.BusinessID, opt.FlowID, opt.UID).Scan(&state); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("d.db.QueryRow error(%v)", err)
return
}
if state == modtask.ActionConsumerOn {
on = true
}
return
}
func (d *Dao) consumer(c context.Context, opt *common.BaseOptions, action int8) (err error) {
var (
res sql.Result
)
res, err = d.db.Exec(c, _consumerSQL, opt.BusinessID, opt.FlowID, opt.UID, action, action)
if err != nil {
log.Error("Exec error(%v)", errors.WithStack(err))
return
}
if _, err = res.RowsAffected(); err != nil {
log.Error("RowsAffected error(%v)", errors.WithStack(err))
return
}
return
}
// ConsumerStat 24小时内有活动或者在线的用户
func (d *Dao) ConsumerStat(c context.Context, bizid, flowid int64) (items []*modtask.WatchItem, err error) {
var rows *xsql.Rows
sql := "SELECT uid,mtime,state from task_consumer where business_id=? AND flow_id=? AND (mtime > ? or state=1) order by mtime desc"
if rows, err = d.db.Query(c, sql, bizid, flowid, time.Now().Add(-24*time.Hour)); err != nil {
log.Error("ConsumerStat error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
item := &modtask.WatchItem{}
if err = rows.Scan(&item.UID, &item.Mtime, &item.State); err != nil {
log.Error("ConsumerStat error(%v)", err)
return
}
items = append(items, item)
}
return
}
// Onlines 在线列表
func (d *Dao) Onlines(c context.Context, opt *common.BaseOptions) (uids map[int64]time.Time, err error) {
var (
rows *xsql.Rows
)
rows, err = d.db.Query(c, _onlinesSQL, opt.BusinessID, opt.FlowID, modtask.ActionConsumerOn)
if err != nil {
log.Error("db.Query error(%v)", err)
return
}
defer rows.Close()
uids = make(map[int64]time.Time)
for rows.Next() {
var (
uid int64
mtime time.Time
)
if err = rows.Scan(&uid, &mtime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
uids[uid] = mtime
}
return
}
// QueryTask .
func (d *Dao) QueryTask(c context.Context, state int8, mtime time.Time, id, limit int64) (tasks []*modtask.Task, lastid int64, err error) {
var rows *xsql.Rows
rows, err = d.db.Query(c, _queryTaskSQL, state, mtime, id, limit)
if err != nil {
log.Error("db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
task := &modtask.Task{}
if err = rows.Scan(&task.ID, &task.BusinessID, &task.FlowID, &task.UID, &task.Weight); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
tasks = append(tasks, task)
lastid = task.ID
}
return
}
// CountPersonal count personal task
func (d *Dao) CountPersonal(c context.Context, opt *common.BaseOptions) (count int64, err error) {
if err = d.db.QueryRow(c, _countPersonalSQL, modtask.TaskStateDispatch, opt.BusinessID, opt.FlowID, opt.UID).Scan(&count); err != nil {
log.Error("QueryRow error(%v)", errors.WithStack(err))
return
}
return
}
// QueryForSeize 查询当前可抢占的任务
func (d *Dao) QueryForSeize(c context.Context, businessID, flowID, uid, seizecount int64) (hitids []int64, err error) {
log.Info("task-QueryForSeize businessID(%d), flowID(%d), uid(%d), seizecount(%d)", businessID, flowID, uid, seizecount)
defer func() { log.Info("task-QueryForSeize hitids(%v), err(%v)", hitids, err) }()
var rows *xsql.Rows
rows, err = d.db.Query(c, _queryForSeizeSQL, modtask.TaskStateInit, businessID, flowID, uid, seizecount)
if err != nil {
log.Error("db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var id int64
if err = rows.Scan(&id); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
hitids = append(hitids, id)
}
return
}

View File

@@ -0,0 +1,305 @@
package mysql
import (
"context"
"testing"
"time"
"go-common/app/admin/main/aegis/model/common"
modtask "go-common/app/admin/main/aegis/model/task"
"github.com/smartystreets/goconvey/convey"
)
func TestMysqlTaskFromDB(t *testing.T) {
convey.Convey("TaskFromDB", t, func(ctx convey.C) {
var (
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
task, err := d.TaskFromDB(cntx, id)
ctx.Convey("Then err should be nil.task should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(task, convey.ShouldBeNil)
})
})
})
}
func TestMysqlDispatchByID(t *testing.T) {
convey.Convey("DispatchByID", t, func(ctx convey.C) {
var (
mtasks map[int64]*modtask.Task
ids = []int64{0}
args = interface{}(int64(0))
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
missids, err := d.DispatchByID(cntx, mtasks, ids, args)
ctx.Convey("Then err should be nil.missids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(missids, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlDBDispatch(t *testing.T) {
convey.Convey("DBDispatch", t, func(ctx convey.C) {
var (
opt = &modtask.NextOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, count, err := d.DBDispatch(cntx, opt)
ctx.Convey("Then err should be nil.tasks,count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlRelease(t *testing.T) {
convey.Convey("Release", t, func(ctx convey.C) {
var (
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
rows, err := d.Release(cntx, opt, true)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlSeize(t *testing.T) {
convey.Convey("Seize", t, func(ctx convey.C) {
var (
c = context.Background()
mapids = map[int64]int64{1: 1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count, err := d.Seize(c, mapids)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlDelay(t *testing.T) {
convey.Convey("Delay", t, func(ctx convey.C) {
var (
opt = &modtask.DelayOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
rows, err := d.Delay(cntx, opt)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlListCheckUnSeized(t *testing.T) {
convey.Convey("ListCheckUnSeized", t, func(ctx convey.C) {
var (
mtasks = map[int64]*modtask.Task{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ListCheckUnSeized(cntx, mtasks, []int64{})
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlListCheckSeized(t *testing.T) {
convey.Convey("ListCheckSeized", t, func(ctx convey.C) {
var (
mtasks = map[int64]*modtask.Task{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ListCheckSeized(cntx, mtasks, []int64{}, int64(1))
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlListCheckDelay(t *testing.T) {
convey.Convey("ListCheckDelay", t, func(ctx convey.C) {
var (
mtasks = map[int64]*modtask.Task{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.ListCheckDelay(cntx, mtasks, []int64{}, int64(1))
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlListTasks(t *testing.T) {
convey.Convey("ListTasks", t, func(ctx convey.C) {
opt := &modtask.ListOptions{
State: 4,
}
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, err := d.ListTasks(context.TODO(), opt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqllistCheck(t *testing.T) {
convey.Convey("listCheck", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.listCheck(context.TODO(), "state=1", []int64{1})
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlConsumerOn(t *testing.T) {
convey.Convey("ConsumerOn", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ConsumerOn(c, opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlConsumerOff(t *testing.T) {
convey.Convey("ConsumerOff", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ConsumerOff(c, opt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlIsConsumerOn(t *testing.T) {
convey.Convey("IsConsumerOn", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
on, err := d.IsConsumerOn(c, opt)
ctx.Convey("Then err should be nil.on should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(on, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlconsumer(t *testing.T) {
convey.Convey("consumer", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
action = int8(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.consumer(c, opt, action)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlConsumerStat(t *testing.T) {
convey.Convey("ConsumerStat", t, func(ctx convey.C) {
var (
c = context.Background()
bizid = int64(0)
flowid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
items, err := d.ConsumerStat(c, bizid, flowid)
ctx.Convey("Then err should be nil.items should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(items, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlOnlines(t *testing.T) {
convey.Convey("Onlines", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
uids, err := d.Onlines(c, opt)
ctx.Convey("Then err should be nil.uids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(uids, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlQueryTask(t *testing.T) {
convey.Convey("QueryTask", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, _, err := d.QueryTask(context.TODO(), 0, time.Now(), 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMysqlCountPersonal(t *testing.T) {
convey.Convey("CountPersonal", t, func(ctx convey.C) {
var (
c = context.Background()
opt = &common.BaseOptions{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count, err := d.CountPersonal(c, opt)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestMysqlQueryForSeize(t *testing.T) {
convey.Convey("QueryForSeize", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.QueryForSeize(context.TODO(), 0, 0, 0, 0)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

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)
})
})
})
}

View File

@@ -0,0 +1,65 @@
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",
"task_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/up/api/v1:go_default_library",
"//vendor/github.com/golang/mock/gomock:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"rpc_mock.go",
"task.go",
],
importpath = "go-common/app/admin/main/aegis/dao/rpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/conf:go_default_library",
"//app/admin/main/aegis/model:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/rpc/client:go_default_library",
"//app/service/main/up/api/v1:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//vendor/github.com/golang/mock/gomock:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"@org_golang_google_grpc//: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,71 @@
package rpc
import (
"context"
"go-common/app/admin/main/aegis/conf"
account "go-common/app/service/main/account/api"
relmod "go-common/app/service/main/relation/model"
relrpc "go-common/app/service/main/relation/rpc/client"
uprpc "go-common/app/service/main/up/api/v1"
"google.golang.org/grpc"
)
// Dao dao
type Dao struct {
c *conf.Config
//gorpc
relRPC RelationRPC
//grpc
AccountClient AccRPC
UpClient UpRPC
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
}
if c.Debug != "local" {
dao.relRPC = relrpc.New(c.RPC.Rel)
var err error
if dao.AccountClient, err = account.NewClient(c.GRPC.AccRPC); err != nil {
panic(err)
}
if dao.UpClient, err = uprpc.NewClient(c.GRPC.UpRPC); err != nil {
panic(err)
}
}
return
}
// Close close the resource.
func (d *Dao) Close() {
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}
//RelationRPC .
type RelationRPC interface {
Stats(c context.Context, arg *relmod.ArgMids) (res map[int64]*relmod.Stat, err error)
}
//AccRPC .
type AccRPC interface {
Info3(ctx context.Context, in *account.MidReq, opts ...grpc.CallOption) (*account.InfoReply, error)
Cards3(ctx context.Context, in *account.MidsReq, opts ...grpc.CallOption) (*account.CardsReply, error)
ProfileWithStat3(ctx context.Context, in *account.MidReq, opts ...grpc.CallOption) (*account.ProfileStatReply, error)
}
//UpRPC .
type UpRPC interface {
UpSpecial(ctx context.Context, in *uprpc.UpSpecialReq, opts ...grpc.CallOption) (*uprpc.UpSpecialReply, error)
UpsSpecial(ctx context.Context, in *uprpc.UpsSpecialReq, opts ...grpc.CallOption) (*uprpc.UpsSpecialReply, error)
UpGroups(ctx context.Context, in *uprpc.NoArgReq, opts ...grpc.CallOption) (*uprpc.UpGroupsReply, error)
}

View File

@@ -0,0 +1,132 @@
package rpc
import (
"context"
"flag"
"fmt"
"os"
"testing"
"go-common/app/admin/main/aegis/conf"
api "go-common/app/service/main/account/api"
relmod "go-common/app/service/main/relation/model"
uprpc "go-common/app/service/main/up/api/v1"
"github.com/golang/mock/gomock"
)
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())
}
var (
_Mid = int64(0)
_Mids = []int64{0, 1, 2}
)
func WithDao(t *testing.T, f func(d *Dao)) func() {
return func() {
mockCtrl := gomock.NewController(t)
accMock := NewMockAccRPC(mockCtrl)
d.AccountClient = accMock
accMock.EXPECT().Cards3(gomock.Any(), &api.MidsReq{Mids: _Mids}).Return(&api.CardsReply{Cards: map[int64]*api.Card{
10086: {
Mid: _Mid,
},
}}, nil).AnyTimes()
relMock := NewMockRelationRPC(mockCtrl)
d.relRPC = relMock
relMock.EXPECT().Stats(gomock.Any(), &relmod.ArgMids{Mids: _Mids}).Return(map[int64]*relmod.Stat{
10086: {
Mid: 10086,
},
}, nil)
f(d)
mockCtrl.Finish()
}
}
func WithMockAccount(t *testing.T, f func(d *Dao)) func() {
return func() {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
accMock := NewMockAccRPC(mockCtrl)
d.AccountClient = accMock
accMock.EXPECT().Info3(gomock.Any(), &api.MidReq{Mid: _Mid}).Return(&api.InfoReply{Info: &api.Info{
Mid: 10086,
}}, nil).AnyTimes()
accMock.EXPECT().Cards3(gomock.Any(), &api.MidsReq{Mids: _Mids}).Return(&api.CardsReply{Cards: map[int64]*api.Card{
10086: {
Mid: _Mid,
},
}}, nil).AnyTimes()
accMock.EXPECT().ProfileWithStat3(gomock.Any(), &api.MidReq{Mid: _Mid}).Return(&api.ProfileStatReply{
Profile: &api.Profile{
Mid: _Mid,
},
}, nil).AnyTimes()
f(d)
}
}
func WithMockRelation(t *testing.T, f func(d *Dao)) func() {
return func() {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
relMock := NewMockRelationRPC(mockCtrl)
d.relRPC = relMock
relMock.EXPECT().Stats(gomock.Any(), &relmod.ArgMids{Mids: _Mids}).Return(map[int64]*relmod.Stat{
10086: {
Mid: 10086,
},
}, nil)
f(d)
}
}
func WithMockUp(t *testing.T, f func(d *Dao)) func() {
return func() {
upspecial := &uprpc.UpSpecial{GroupIDs: []int64{1}}
upspecialreply := &uprpc.UpSpecialReply{UpSpecial: upspecial}
upspecialsreply := &uprpc.UpsSpecialReply{UpSpecials: map[int64]*uprpc.UpSpecial{0: upspecial}}
upgroupsreply := &uprpc.UpGroupsReply{UpGroups: map[int64]*uprpc.UpGroup{0: {ID: 0}}}
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
upMock := NewMockUpRPC(mockCtrl)
d.UpClient = upMock
upMock.EXPECT().UpSpecial(gomock.Any(), &uprpc.UpSpecialReq{Mid: _Mid}).Return(upspecialreply, nil)
upMock.EXPECT().UpsSpecial(gomock.Any(), &uprpc.UpsSpecialReq{Mids: _Mids}).Return(upspecialsreply, nil)
upMock.EXPECT().UpGroups(gomock.Any(), &uprpc.NoArgReq{}).Return(upgroupsreply, nil)
f(d)
}
}

View File

@@ -0,0 +1,207 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: /Users/danbeiti/go/src/go-common/app/admin/main/aegis/dao/rpc/dao.go
// Package mock is a generated GoMock package.
package rpc
import (
context "context"
reflect "reflect"
api "go-common/app/service/main/account/api"
model "go-common/app/service/main/relation/model"
v1 "go-common/app/service/main/up/api/v1"
gomock "github.com/golang/mock/gomock"
grpc "google.golang.org/grpc"
)
// MockRelationRPC is a mock of RelationRPC interface
type MockRelationRPC struct {
ctrl *gomock.Controller
recorder *MockRelationRPCMockRecorder
}
// MockRelationRPCMockRecorder is the mock recorder for MockRelationRPC
type MockRelationRPCMockRecorder struct {
mock *MockRelationRPC
}
// NewMockRelationRPC creates a new mock instance
func NewMockRelationRPC(ctrl *gomock.Controller) *MockRelationRPC {
mock := &MockRelationRPC{ctrl: ctrl}
mock.recorder = &MockRelationRPCMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockRelationRPC) EXPECT() *MockRelationRPCMockRecorder {
return m.recorder
}
// Stats mocks base method
func (m *MockRelationRPC) Stats(c context.Context, arg *model.ArgMids) (map[int64]*model.Stat, error) {
ret := m.ctrl.Call(m, "Stats", c, arg)
ret0, _ := ret[0].(map[int64]*model.Stat)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Stats indicates an expected call of Stats
func (mr *MockRelationRPCMockRecorder) Stats(c, arg interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stats", reflect.TypeOf((*MockRelationRPC)(nil).Stats), c, arg)
}
// MockAccRPC is a mock of AccRPC interface
type MockAccRPC struct {
ctrl *gomock.Controller
recorder *MockAccRPCMockRecorder
}
// MockAccRPCMockRecorder is the mock recorder for MockAccRPC
type MockAccRPCMockRecorder struct {
mock *MockAccRPC
}
// NewMockAccRPC creates a new mock instance
func NewMockAccRPC(ctrl *gomock.Controller) *MockAccRPC {
mock := &MockAccRPC{ctrl: ctrl}
mock.recorder = &MockAccRPCMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockAccRPC) EXPECT() *MockAccRPCMockRecorder {
return m.recorder
}
// Info3 mocks base method
func (m *MockAccRPC) Info3(ctx context.Context, in *api.MidReq, opts ...grpc.CallOption) (*api.InfoReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Info3", varargs...)
ret0, _ := ret[0].(*api.InfoReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Info3 indicates an expected call of Info3
func (mr *MockAccRPCMockRecorder) Info3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info3", reflect.TypeOf((*MockAccRPC)(nil).Info3), varargs...)
}
// Cards3 mocks base method
func (m *MockAccRPC) Cards3(ctx context.Context, in *api.MidsReq, opts ...grpc.CallOption) (*api.CardsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Cards3", varargs...)
ret0, _ := ret[0].(*api.CardsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Cards3 indicates an expected call of Cards3
func (mr *MockAccRPCMockRecorder) Cards3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cards3", reflect.TypeOf((*MockAccRPC)(nil).Cards3), varargs...)
}
// ProfileWithStat3 mocks base method
func (m *MockAccRPC) ProfileWithStat3(ctx context.Context, in *api.MidReq, opts ...grpc.CallOption) (*api.ProfileStatReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "ProfileWithStat3", varargs...)
ret0, _ := ret[0].(*api.ProfileStatReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ProfileWithStat3 indicates an expected call of ProfileWithStat3
func (mr *MockAccRPCMockRecorder) ProfileWithStat3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProfileWithStat3", reflect.TypeOf((*MockAccRPC)(nil).ProfileWithStat3), varargs...)
}
// MockUpRPC is a mock of UpRPC interface
type MockUpRPC struct {
ctrl *gomock.Controller
recorder *MockUpRPCMockRecorder
}
// MockUpRPCMockRecorder is the mock recorder for MockUpRPC
type MockUpRPCMockRecorder struct {
mock *MockUpRPC
}
// NewMockUpRPC creates a new mock instance
func NewMockUpRPC(ctrl *gomock.Controller) *MockUpRPC {
mock := &MockUpRPC{ctrl: ctrl}
mock.recorder = &MockUpRPCMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockUpRPC) EXPECT() *MockUpRPCMockRecorder {
return m.recorder
}
// UpSpecial mocks base method
func (m *MockUpRPC) UpSpecial(ctx context.Context, in *v1.UpSpecialReq, opts ...grpc.CallOption) (*v1.UpSpecialReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "UpSpecial", varargs...)
ret0, _ := ret[0].(*v1.UpSpecialReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpSpecial indicates an expected call of UpSpecial
func (mr *MockUpRPCMockRecorder) UpSpecial(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpSpecial", reflect.TypeOf((*MockUpRPC)(nil).UpSpecial), varargs...)
}
// UpsSpecial mocks base method
func (m *MockUpRPC) UpsSpecial(ctx context.Context, in *v1.UpsSpecialReq, opts ...grpc.CallOption) (*v1.UpsSpecialReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "UpsSpecial", varargs...)
ret0, _ := ret[0].(*v1.UpsSpecialReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpsSpecial indicates an expected call of UpsSpecial
func (mr *MockUpRPCMockRecorder) UpsSpecial(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsSpecial", reflect.TypeOf((*MockUpRPC)(nil).UpsSpecial), varargs...)
}
// UpGroups mocks base method
func (m *MockUpRPC) UpGroups(ctx context.Context, in *v1.NoArgReq, opts ...grpc.CallOption) (*v1.UpGroupsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "UpGroups", varargs...)
ret0, _ := ret[0].(*v1.UpGroupsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpGroups indicates an expected call of UpGroups
func (mr *MockUpRPCMockRecorder) UpGroups(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpGroups", reflect.TypeOf((*MockUpRPC)(nil).UpGroups), varargs...)
}

View File

@@ -0,0 +1,181 @@
package rpc
import (
"context"
"errors"
"go-common/app/admin/main/aegis/model"
acc "go-common/app/service/main/account/api"
relmod "go-common/app/service/main/relation/model"
uprpc "go-common/app/service/main/up/api/v1"
"go-common/library/log"
"go-common/library/net/metadata"
terrors "github.com/pkg/errors"
)
//ERROR
var (
ErrEmptyReply = errors.New("rpc empty reply")
)
// FansCount 粉丝数
func (d *Dao) FansCount(c context.Context, mids []int64) (fans map[int64]int64, err error) {
arg := &relmod.ArgMids{Mids: mids}
stats, err := d.relRPC.Stats(c, arg)
if err != nil {
log.Error("FansCount error(%v)", terrors.WithStack(err))
return
}
fans = make(map[int64]int64)
for mid, item := range stats {
fans[mid] = item.Follower
}
log.Info("FansCount fans(%+v)", fans)
return
}
// UserInfos 提供给资源列表批量查
func (d *Dao) UserInfos(c context.Context, mids []int64) (res map[int64]*model.UserInfo, err error) {
arg1 := &relmod.ArgMids{Mids: mids}
stats, err := d.relRPC.Stats(c, arg1)
if err != nil {
log.Error("Stats error(%v)", terrors.WithStack(err))
return
}
midsReq := &acc.MidsReq{
Mids: mids,
RealIp: metadata.String(c, metadata.RemoteIP),
}
cardsreply, err := d.AccountClient.Cards3(c, midsReq)
if err != nil {
log.Error("Cards3(%+v) error(%v)", mids, terrors.WithStack(err))
return
}
if cardsreply == nil {
err = ErrEmptyReply
log.Error("Cards3(%+v) error(%v)", mids, terrors.WithStack(err))
return
}
cards := cardsreply.Cards
res = make(map[int64]*model.UserInfo)
for _, mid := range mids {
userinfo := &model.UserInfo{Mid: mid}
if card, ok := cards[mid]; ok {
userinfo.Name = card.Name
userinfo.Official = card.Official
}
if stat, ok := stats[mid]; ok {
userinfo.Follower = stat.Follower
}
res[mid] = userinfo
}
return
}
// Profile get account.
func (d *Dao) Profile(c context.Context, mid int64) (userinfo *model.UserInfo, err error) {
if mid <= 0 {
return
}
midReq := &acc.MidReq{
Mid: mid,
RealIp: metadata.String(c, metadata.RemoteIP),
}
res, err := d.AccountClient.ProfileWithStat3(c, midReq)
if err != nil {
log.Error("d.acc.ProfileWithStat3() error(%v) arg(%+v)", err, midReq)
}
if res == nil {
err = ErrEmptyReply
log.Error("ProfileWithStat3(%+v) error(%v)", mid, terrors.WithStack(err))
return
}
userinfo = &model.UserInfo{
Mid: mid,
Follower: res.Follower,
}
if res.Profile != nil {
userinfo.Official = res.Profile.Official
userinfo.Name = res.Profile.Name
}
return
}
// Info3 get Name.
func (d *Dao) Info3(c context.Context, mid int64) (res *acc.Info, err error) {
midReq := &acc.MidReq{
Mid: mid,
RealIp: metadata.String(c, metadata.RemoteIP),
}
info, err := d.AccountClient.Info3(c, midReq)
if err != nil {
log.Error("query info3 failed,mid(%v), err(%v)", mid, err)
return
}
if info == nil {
err = ErrEmptyReply
log.Error("Info3(%+v) error(%v)", mid, terrors.WithStack(err))
return
}
res = info.Info
log.Info("getUserInfo userbase (%v)", res)
return
}
// UpSpecial 分组信息
func (d *Dao) UpSpecial(c context.Context, mid int64) (ups *uprpc.UpSpecial, err error) {
midReq := &uprpc.UpSpecialReq{
Mid: mid,
}
var reply *uprpc.UpSpecialReply
if reply, err = d.UpClient.UpSpecial(c, midReq); err != nil {
log.Error("UpSpecial(%d) error(%v)", mid, terrors.WithStack(err))
return
}
if reply == nil {
err = ErrEmptyReply
log.Error("UpSpecial(%+v) error(%v)", mid, terrors.WithStack(err))
return
}
ups = reply.UpSpecial
return
}
//UpsSpecial 分组信息
func (d *Dao) UpsSpecial(c context.Context, mids []int64) (ups map[int64]*uprpc.UpSpecial, err error) {
midReq := &uprpc.UpsSpecialReq{
Mids: mids,
}
var reply *uprpc.UpsSpecialReply
if reply, err = d.UpClient.UpsSpecial(c, midReq); err != nil {
log.Error("UpsSpecial(%d) error(%v)", mids, terrors.WithStack(err))
return
}
if reply == nil {
err = ErrEmptyReply
log.Error("UpsSpecial(%+v) error(%v)", mids, terrors.WithStack(err))
return
}
ups = reply.UpSpecials
return
}
//UpGroups 所有分组
func (d *Dao) UpGroups(c context.Context) (upgs map[int64]*uprpc.UpGroup, err error) {
noReq := &uprpc.NoArgReq{}
var reply *uprpc.UpGroupsReply
if reply, err = d.UpClient.UpGroups(c, noReq); err != nil {
log.Error("UpGroups error(%v)", terrors.WithStack(err))
return
}
if reply == nil {
err = ErrEmptyReply
log.Error("UpGroups error(%v)", terrors.WithStack(err))
return
}
upgs = reply.UpGroups
return
}

View File

@@ -0,0 +1,53 @@
package rpc
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestRpcFansCount(t *testing.T) {
Convey("FansCount", t, WithMockRelation(t, func(d *Dao) {
res, err := d.FansCount(context.TODO(), _Mids)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestRpcUserInfos(t *testing.T) {
Convey("UserInfos", t, WithDao(t, func(d *Dao) {
res, err := d.UserInfos(context.TODO(), _Mids)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestRpcProfile(t *testing.T) {
Convey("Profile", t, WithMockAccount(t, func(d *Dao) {
res, err := d.Profile(context.TODO(), _Mid)
So(err, ShouldBeNil)
So(res, ShouldBeNil)
}))
}
func TestRpcInfo3(t *testing.T) {
Convey("Info3", t, WithMockAccount(t, func(d *Dao) {
res, err := d.Info3(context.TODO(), _Mid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestRpcUpSpecial(t *testing.T) {
Convey("UpSpecial", t, WithMockUp(t, func(d *Dao) {
res1, err := d.UpSpecial(context.TODO(), _Mid)
So(err, ShouldBeNil)
So(res1, ShouldNotBeNil)
res2, err := d.UpsSpecial(context.TODO(), _Mids)
So(err, ShouldBeNil)
So(res2, ShouldNotBeNil)
res3, err := d.UpGroups(context.TODO())
So(err, ShouldBeNil)
So(res3, ShouldNotBeNil)
}))
}