Create & Init Project...

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

View File

@@ -0,0 +1,83 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.cache.go",
"dao.go",
"mc.go",
"passport.go",
"raw.go",
"realname.go",
"search.go",
"vip.go",
],
importpath = "go-common/app/service/main/account/dao",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/member/api/gorpc:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/member/model/block:go_default_library",
"//app/service/main/usersuit/model:go_default_library",
"//app/service/main/usersuit/rpc/client:go_default_library",
"//library/cache/memcache: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/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao.cache_test.go",
"dao_test.go",
"mc_test.go",
"passport_test.go",
"raw_test.go",
"search_test.go",
"vip_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/member/model/block:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,376 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package dao is a generated cache proxy package.
It is generated from:
type _cache interface {
Info(c context.Context, key int64) (*v1.Info, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Infos(c context.Context, keys []int64) (map[int64]*v1.Info, error)
Card(c context.Context, key int64) (*v1.Card, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Cards(c context.Context, keys []int64) (map[int64]*v1.Card, error)
Vip(c context.Context, key int64) (*v1.VipInfo, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Vips(c context.Context, keys []int64) (map[int64]*v1.VipInfo, error)
Profile(c context.Context, key int64) (*v1.Profile, error)
}
*/
package dao
import (
"context"
"sync"
v1 "go-common/app/service/main/account/api"
"go-common/library/stat/prom"
"go-common/library/sync/errgroup"
)
var _ _cache
// Info get data from cache if miss will call source method, then add to cache.
func (d *Dao) Info(c context.Context, id int64) (res *v1.Info, err error) {
addCache := true
res, err = d.CacheInfo(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Info")
return
}
prom.CacheMiss.Incr("Info")
res, err = d.RawInfo(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheInfo(ctx, id, miss)
})
return
}
// Infos get data from cache if miss will call source method, then add to cache.
func (d *Dao) Infos(c context.Context, keys []int64) (res map[int64]*v1.Info, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheInfos(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Infos", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.Info
missLen := len(miss)
prom.CacheMiss.Add("Infos", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawInfos(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.Info, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.Info)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheInfos(ctx, missData)
})
return
}
// Card cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Card(c context.Context, id int64) (res *v1.Card, err error) {
addCache := true
res, err = d.CacheCard(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Card")
return
}
prom.CacheMiss.Incr("Card")
res, err = d.RawCard(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheCard(ctx, id, miss)
})
return
}
// Cards get data from cache if miss will call source method, then add to cache.
func (d *Dao) Cards(c context.Context, keys []int64) (res map[int64]*v1.Card, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheCards(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Cards", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.Card
missLen := len(miss)
prom.CacheMiss.Add("Cards", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawCards(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.Card, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.Card)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheCards(ctx, missData)
})
return
}
// Vip cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Vip(c context.Context, id int64) (res *v1.VipInfo, err error) {
addCache := true
res, err = d.CacheVip(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Vip")
return
}
prom.CacheMiss.Incr("Vip")
res, err = d.RawVip(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheVip(ctx, id, miss)
})
return
}
// Vips get data from cache if miss will call source method, then add to cache.
func (d *Dao) Vips(c context.Context, keys []int64) (res map[int64]*v1.VipInfo, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheVips(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Vips", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.VipInfo
missLen := len(miss)
prom.CacheMiss.Add("Vips", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawVips(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.VipInfo, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.VipInfo)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheVips(ctx, missData)
})
return
}
// Profile cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Profile(c context.Context, id int64) (res *v1.Profile, err error) {
addCache := true
res, err = d.CacheProfile(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Profile")
return
}
prom.CacheMiss.Incr("Profile")
res, err = d.RawProfile(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheProfile(ctx, id, miss)
})
return
}

View File

@@ -0,0 +1,126 @@
package dao
import (
"context"
"testing"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoInfo(t *testing.T) {
var (
c = context.TODO()
id = int64(1405)
)
convey.Convey("Get base-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Info(c, id)
ctx.Convey("Then err should be nil and res should be not nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoInfos(t *testing.T) {
var (
c = context.TODO()
keys = []int64{110020171, 110019841}
)
convey.Convey("Batch get base-infos from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Infos(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoCard(t *testing.T) {
var (
c = context.TODO()
id = int64(110020171)
)
convey.Convey("Get card-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Card(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoCards(t *testing.T) {
var (
c = context.TODO()
keys = []int64{110020171, 110019841}
)
convey.Convey("Batch get card-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Cards(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoVip(t *testing.T) {
var (
c = context.TODO()
id = int64(110018881)
)
convey.Convey("Get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vip(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAutoRenewVip(t *testing.T) {
var (
c = context.TODO()
autoRenewMid = int64(27515232)
)
convey.Convey("Get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vip(c, autoRenewMid)
t.Logf("data(%+v)", res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoVips(t *testing.T) {
var (
c = context.TODO()
keys = []int64{1405, 2205}
)
convey.Convey("Batch get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vips(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoProfile(t *testing.T) {
var (
c = context.TODO()
id = int64(111003471)
)
convey.Convey("Get profile-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Profile(c, id)
if err == ecode.Degrade {
err = nil
}
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,138 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/conf"
member "go-common/app/service/main/member/api/gorpc"
mmodel "go-common/app/service/main/member/model"
usersuit "go-common/app/service/main/usersuit/rpc/client"
"go-common/library/cache/memcache"
"go-common/library/database/elastic"
bm "go-common/library/net/http/blademaster"
"go-common/library/sync/pipeline/fanout"
)
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
Info(c context.Context, key int64) (*v1.Info, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Infos(c context.Context, keys []int64) (map[int64]*v1.Info, error)
Card(c context.Context, key int64) (*v1.Card, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Cards(c context.Context, keys []int64) (map[int64]*v1.Card, error)
Vip(c context.Context, key int64) (*v1.VipInfo, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Vips(c context.Context, keys []int64) (map[int64]*v1.VipInfo, error)
Profile(c context.Context, key int64) (*v1.Profile, error)
}
const (
_nameURL = "/api/member/getInfoByName"
_vipInfoURL = "/internal/v1/user/%d"
_vipMultiInfoURL = "/internal/v1/user/list"
_passportDetailURL = "/intranet/acc/detail"
_passportProfile = "/intranet/acc/queryByMid"
)
// Dao dao.
type Dao struct {
// memcache
mc *memcache.Pool
mcExpire int32
// cache async save
cache *fanout.Fanout
// rpc
mRPC *member.Service
suitRPC *usersuit.Service2
// http
httpR *bm.Client
httpW *bm.Client
httpP *bm.Client
// api
detailURI string
profileURI string
nameURI string
// vip api
vipInfoURI string
vipMultiInfoURI string
//es
es *elastic.Elastic
}
// New new a dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// account memcache
mc: memcache.NewPool(c.Memcache.Account),
mcExpire: int32(time.Duration(c.Memcache.AccountExpire) / time.Second),
// cache chan
cache: fanout.New("accountServiceCache", fanout.Worker(1), fanout.Buffer(1024)),
// rpc
// mRPC: member.New(c.MemberRPC),
mRPC: member.New(c.MemberRPC),
suitRPC: usersuit.New(c.SuitRPC),
// http read&write client
httpR: bm.NewClient(c.HTTPClient.Read),
httpW: bm.NewClient(c.HTTPClient.Write),
httpP: bm.NewClient(c.HTTPClient.Privacy),
es: elastic.NewElastic(c.Elastic),
// api
nameURI: c.Host.AccountURI + _nameURL,
// vip api
vipInfoURI: c.Host.VipURI + _vipInfoURL,
vipMultiInfoURI: c.Host.VipURI + _vipMultiInfoURL,
//passport
detailURI: c.Host.PassportURI + _passportDetailURL,
profileURI: c.Host.PassportURI + _passportProfile,
}
return
}
// LevelExp get member level exp.
func (d *Dao) LevelExp(c context.Context, mid int64) (lexp *mmodel.LevelInfo, err error) {
lexp, err = d.mRPC.Exp(c, &mmodel.ArgMid2{Mid: mid})
return
}
// AddMoral add moral.
func (d *Dao) AddMoral(c context.Context, arg *mmodel.ArgUpdateMoral) (err error) {
return d.mRPC.AddMoral(c, arg)
}
// UpdateExp update exp.
func (d *Dao) UpdateExp(c context.Context, arg *mmodel.ArgAddExp) error {
return d.mRPC.UpdateExp(c, arg)
}
// Ping check connection success.
func (d *Dao) Ping(c context.Context) (err error) {
conn := d.mc.Get(c)
err = conn.Set(&memcache.Item{
Key: "ping",
Value: []byte("pong"),
})
conn.Close()
return
}
// Close close memcache resource.
func (d *Dao) Close() {
if d.mc != nil {
d.mc.Close()
}
}
func fullImage(mid int64, image string) string {
if len(image) == 0 {
return ""
}
if strings.HasPrefix(image, "http://") {
return image
}
return fmt.Sprintf("http://i%d.hdslb.com%s", mid%3, image)
}

View File

@@ -0,0 +1,35 @@
package dao
import (
"flag"
"go-common/app/service/main/account/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.account-service")
flag.Set("conf_token", "187c672d88909792e47cd2fbc9ccc070")
flag.Set("tree_id", "2318")
flag.Set("conf_version", "docker-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/account-service-example.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,364 @@
package dao
import (
"context"
"strconv"
"github.com/pkg/errors"
v1 "go-common/app/service/main/account/api"
mc "go-common/library/cache/memcache"
)
const (
_prefixInfo = "i3_"
_prefixCard = "c3_"
_prefixVip = "v3_"
_prefixProfile = "p3_"
)
func keyInfo(mid int64) string {
return _prefixInfo + strconv.FormatInt(mid, 10)
}
func keyCard(mid int64) string {
return _prefixCard + strconv.FormatInt(mid, 10)
}
func keyVip(mid int64) string {
return _prefixVip + strconv.FormatInt(mid, 10)
}
func keyProfile(mid int64) string {
return _prefixProfile + strconv.FormatInt(mid, 10)
}
// CacheInfo get account info from cache.
func (d *Dao) CacheInfo(c context.Context, mid int64) (v *v1.Info, err error) {
key := keyInfo(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cache info")
return
}
v = &v1.Info{}
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao cache scan info")
}
return
}
// AddCacheInfo set account info into cache.
func (d *Dao) AddCacheInfo(c context.Context, mid int64, v *v1.Info) (err error) {
item := &mc.Item{
Key: keyInfo(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao add info cache")
}
return
}
// CacheInfos multi get account info from cache.
func (d *Dao) CacheInfos(c context.Context, mids []int64) (res map[int64]*v1.Info, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyInfo(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao infos cache")
return
}
res = make(map[int64]*v1.Info, len(mids))
for _, r := range rs {
ai := &v1.Info{}
conn.Scan(r, ai)
res[ai.Mid] = ai
}
return
}
// AddCacheInfos set account infos cache.
func (d *Dao) AddCacheInfos(c context.Context, im map[int64]*v1.Info) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for _, i := range im {
item := &mc.Item{
Key: keyInfo(i.Mid),
Object: i,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add infos cache")
}
}
return
}
// CacheCard get account card from cache.
func (d *Dao) CacheCard(c context.Context, mid int64) (v *v1.Card, err error) {
key := keyCard(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cache card")
return
}
v = &v1.Card{}
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao cache scan card")
}
return
}
// AddCacheCard set account card into cache.
func (d *Dao) AddCacheCard(c context.Context, mid int64, v *v1.Card) (err error) {
item := &mc.Item{
Key: keyCard(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao add card cache")
}
return
}
// CacheCards multi get account cards from cache.
func (d *Dao) CacheCards(c context.Context, mids []int64) (res map[int64]*v1.Card, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyCard(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cards cache")
return
}
res = make(map[int64]*v1.Card, len(mids))
for _, r := range rs {
ai := &v1.Card{}
conn.Scan(r, ai)
res[ai.Mid] = ai
}
return
}
// AddCacheCards set account cards cache.
func (d *Dao) AddCacheCards(c context.Context, cm map[int64]*v1.Card) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for _, card := range cm {
item := &mc.Item{
Key: keyCard(card.Mid),
Object: card,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add cards cache")
}
}
return
}
// CacheVip get vip cache.
func (d *Dao) CacheVip(c context.Context, mid int64) (v *v1.VipInfo, err error) {
key := keyVip(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao vip cache")
return
}
v = new(v1.VipInfo)
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao vip cache scan")
}
return
}
// AddCacheVip set vip cache.
func (d *Dao) AddCacheVip(c context.Context, mid int64, v *v1.VipInfo) (err error) {
conn := d.mc.Get(c)
conn.Set(&mc.Item{
Key: keyVip(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
})
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao vip add cache")
}
return
}
// CacheVips multi get account cards from cache.
func (d *Dao) CacheVips(c context.Context, mids []int64) (res map[int64]*v1.VipInfo, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyVip(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao vips cache")
return
}
res = make(map[int64]*v1.VipInfo, len(mids))
for _, r := range rs {
ai := &v1.VipInfo{}
conn.Scan(r, ai)
res[keyMidMap[r.Key]] = ai
}
return
}
// AddCacheVips set account vips cache.
func (d *Dao) AddCacheVips(c context.Context, vm map[int64]*v1.VipInfo) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for mid, v := range vm {
item := &mc.Item{
Key: keyVip(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add vips cache")
}
}
return
}
// CacheProfile get profile cache.
func (d *Dao) CacheProfile(c context.Context, mid int64) (v *v1.Profile, err error) {
key := keyProfile(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao profile cache")
return
}
v = new(v1.Profile)
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao profile cache scan")
}
return
}
// AddCacheProfile set profile cache.
func (d *Dao) AddCacheProfile(c context.Context, mid int64, v *v1.Profile) (err error) {
conn := d.mc.Get(c)
conn.Set(&mc.Item{
Key: keyProfile(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
})
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao profile add cache")
}
return
}
// DelCache delete cache.
func (d *Dao) DelCache(c context.Context, mid int64) []error {
conn := d.mc.Get(c)
errs := make([]error, 0, 5)
if err := conn.Delete(keyInfo(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyInfo(mid)))
}
if err := conn.Delete(keyCard(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyCard(mid)))
}
if err := conn.Delete(keyVip(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyVip(mid)))
}
if err := conn.Delete(keyProfile(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyProfile(mid)))
}
if err := conn.Close(); err != nil {
errs = append(errs, errors.Wrap(err, "conn close"))
}
d.cache.Do(c, func(ctx context.Context) {
d.Info(ctx, mid)
d.Card(ctx, mid)
d.Vip(ctx, mid)
d.Profile(ctx, mid)
})
return errs
}

View File

@@ -0,0 +1,397 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/account/model"
mc "go-common/library/cache/memcache"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyInfo(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate info-key", t, func(ctx convey.C) {
p1 := keyInfo(mid)
ctx.Convey("Then info-key should contains info prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixInfo)
})
})
}
func TestDaokeyCard(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate card-info-key", t, func(ctx convey.C) {
p1 := keyCard(mid)
ctx.Convey("Then card-info-key should contains card prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixCard)
})
})
}
func TestDaokeyVip(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate vip-info-key", t, func(ctx convey.C) {
p1 := keyVip(mid)
ctx.Convey("Then vip-info-key should contains vip prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixVip)
})
})
}
func TestDaokeyProfile(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate profile-key", t, func(ctx convey.C) {
p1 := keyProfile(mid)
ctx.Convey("Then profile-key should contains profile prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixProfile)
})
})
}
func TestDaoCacheInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(2205)
)
convey.Convey("Get member base-info from cache", t, func(ctx convey.C) {
_, err := d.CacheInfo(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(2205)
v = &model.Info{
Mid: 2205,
Name: "Haha",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来电只是",
Rank: 500,
}
)
convey.Convey("Add member base-info to cache", t, func(ctx convey.C) {
err := d.AddCacheInfo(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheInfos(t *testing.T) {
var (
c = context.TODO()
mids = []int64{2205, 2805}
)
convey.Convey("Batch get members' base-info", t, func(ctx convey.C) {
res, err := d.CacheInfos(c, mids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheInfos(t *testing.T) {
var (
c = context.TODO()
im = map[int64]*model.Info{
2205: {
Mid: 2205,
Name: "板桥真菜",
Sex: "2",
Face: "/bfs/face/e93098c3aa8c18b24001740e707ebe2df180f5f7.jpg",
Sign: "没有",
Rank: 10000,
},
3305: {
Mid: 3305,
Name: "FGNB",
Sex: "1",
Face: "/bfs/face/e93098c3aa8c18b24001740e707ebe2df180f5f7.jpg",
Sign: "啦啦",
Rank: 5000,
},
}
)
convey.Convey("Batch set members' base-info to cache", t, func(ctx convey.C) {
err := d.AddCacheInfos(c, im)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(2805)
)
convey.Convey("Get card-info from cache", t, func(ctx convey.C) {
_, err := d.CacheCard(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(2805)
v = &model.Card{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5, //等级
Silence: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1566367231,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频",
},
}
)
convey.Convey("Add card-info to cache", t, func(ctx convey.C) {
err := d.AddCacheCard(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheCards(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110017381, 110019061, 110020081}
)
convey.Convey("Batch get card-info from cache", t, func(ctx convey.C) {
res, err := d.CacheCards(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheCards(t *testing.T) {
var (
c = context.TODO()
card1 = &model.Card{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5, //等级
Silence: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1566367231,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频",
},
}
cm = map[int64]*model.Card{
card1.Mid: card1,
}
)
convey.Convey("Batch set card-info to cache", t, func(ctx convey.C) {
err := d.AddCacheCards(c, cm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110003731)
)
convey.Convey("Get vip-info from cache", t, func(ctx convey.C) {
_, err := d.CacheVip(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110003731)
v = &model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
}
)
convey.Convey("Set vip-cache to cache", t, func(ctx convey.C) {
err := d.AddCacheVip(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheVips(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110002741, 110004601, 110006251}
)
convey.Convey("Batch get vip-infos from cache", t, func(ctx convey.C) {
res, err := d.CacheVips(c, mids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheVips(t *testing.T) {
var (
c = context.TODO()
vm = map[int64]*model.VipInfo{
110007391: {
Type: 2,
Status: 1,
DueDate: 162930240,
},
110010271: {
Type: 2,
Status: 1,
DueDate: 162930240,
},
}
)
convey.Convey("Batch set vip-infos to cache", t, func(ctx convey.C) {
err := d.AddCacheVips(c, vm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110011831)
)
convey.Convey("Get profile-info from cache", t, func(ctx convey.C) {
_, err := d.CacheProfile(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110011951)
v = &model.Profile{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5,
JoinTime: 1503296503,
Moral: 71,
Silence: 0,
EmailStatus: 1,
TelStatus: 1,
Identification: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 1629302400000,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1551413548,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频投稿通过总数>=10",
},
}
)
convey.Convey("Set profile-info to cache", t, func(ctx convey.C) {
err := d.AddCacheProfile(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(110014081)
)
convey.Convey("Delete member's cache", t, func(ctx convey.C) {
errs := d.DelCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
for _, e := range errs {
if e != mc.ErrNotFound {
ctx.So(e, convey.ShouldBeNil)
}
}
})
})
}

View File

@@ -0,0 +1,64 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/app/service/main/account/model"
"go-common/library/ecode"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
// PassportDetail get detail.
func (d *Dao) PassportDetail(c context.Context, mid int64) (res *model.PassportDetail, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
// params.Set("access_key", accessKey)
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Info *model.PassportDetail `json:"data"`
}
req, err := d.httpR.NewRequest("GET", d.detailURI, ip, params)
if err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
// req.Header.Set("Cookie", cookie)
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
if err = d.httpR.Do(c, req, &resp); err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
if resp.Code != 0 {
err = ecode.Int(resp.Code)
err = errors.Wrap(err, "dao passport detail")
return
}
res = resp.Info
return
}
// PassportProfile is.
func (d *Dao) PassportProfile(c context.Context, mid int64, ip string) (res *model.PassportProfile, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Data *model.PassportProfile `json:"data"`
}
if err = d.httpP.Get(c, d.profileURI, ip, params, &resp); err != nil {
err = errors.Wrap(err, "dao passport profile")
return nil, err
}
if resp.Code != 0 {
err = ecode.Int(resp.Code)
err = errors.WithStack(err)
return
}
res = resp.Data
return
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPassportDetail(t *testing.T) {
var (
c = context.TODO()
mid = int64(110016931)
)
convey.Convey("Get passport detail", t, func(ctx convey.C) {
res, err := d.PassportDetail(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,389 @@
package dao
import (
"context"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
mml "go-common/app/service/main/member/model"
bml "go-common/app/service/main/member/model/block"
sml "go-common/app/service/main/usersuit/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"github.com/pkg/errors"
)
// RawInfo raw info.
func (d *Dao) RawInfo(c context.Context, mid int64) (res *v1.Info, err error) {
var base *mml.BaseInfo
if base, err = d.mRPC.Base(c, &mml.ArgMemberMid{Mid: mid}); err != nil {
// err = errors.Wrap(err, "dao raw info")
// err = errors.WithStack(err)
return
}
res = &v1.Info{
Mid: base.Mid,
Name: base.Name,
Sex: base.SexStr(),
Face: base.Face,
Sign: base.Sign,
Rank: int32(base.Rank),
}
return
}
// RawInfos raw infos.
func (d *Dao) RawInfos(c context.Context, mids []int64) (res map[int64]*v1.Info, err error) {
var bm map[int64]*mml.BaseInfo
if bm, err = d.mRPC.Bases(c, &mml.ArgMemberMids{Mids: mids}); err != nil {
// err = errors.Wrap(err, "dao raw info")
err = errors.WithStack(err)
return
}
res = map[int64]*v1.Info{}
for _, base := range bm {
i := &v1.Info{
Mid: base.Mid,
Name: base.Name,
Sex: base.SexStr(),
Face: base.Face,
Sign: base.Sign,
Rank: int32(base.Rank),
}
res[i.Mid] = i
}
return
}
// RawCard get card by mid.
func (d *Dao) RawCard(c context.Context, mid int64) (res *v1.Card, err error) {
eg, _ := errgroup.WithContext(c)
var mb *mml.Member
eg.Go(func() (e error) {
if mb, e = d.mRPC.Member(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
// e = ecode.Degrade
}
return
})
var medal *sml.MedalInfo
eg.Go(func() (e error) {
if medal, e = d.suitRPC.MedalActivated(c, &sml.ArgMid{Mid: mid}); e != nil {
log.Error("s.suitRPC.MedalActivated(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var block *bml.RPCResInfo
eg.Go(func() (e error) {
if block, e = d.mRPC.BlockInfo(c, &bml.RPCArgInfo{MID: mid}); e != nil {
log.Error("d.block.BlockInfo(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var vip *v1.VipInfo
eg.Go(func() (e error) {
if vip, e = d.Vip(c, mid); e != nil {
log.Error("d.Vip(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var pendant *sml.PendantEquip
eg.Go(func() (e error) {
if pendant, e = d.suitRPC.Equipment(c, &sml.ArgEquipment{Mid: mid}); e != nil {
log.Error("d.suitRPC.Equipment(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
card := &v1.Card{Mid: mid}
if medal != nil {
card.Nameplate.Nid = int(medal.ID)
card.Nameplate.Name = medal.Name
card.Nameplate.Image = medal.Image
card.Nameplate.ImageSmall = medal.ImageSmall
card.Nameplate.Level = medal.LevelDesc
card.Nameplate.Condition = medal.Condition
}
if block != nil {
card.Silence = blockStatusToSilence(block.BlockStatus)
}
if mb != nil {
card.Name = mb.Name
card.Sign = mb.Sign
card.Sex = mb.SexStr()
card.Rank = int32(mb.Rank)
card.Face = mb.Face
if mb.OfficialInfo != nil {
// card.Official = *mb.OfficialInfo
card.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
card.Level = mb.Cur
}
if vip != nil {
card.Vip = *vip
}
if pendant != nil {
card.Pendant.Pid = int(pendant.Pid)
card.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
card.Pendant.Name = pendant.Pendant.Name
card.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res = card
return
}
// RawCards get card by mid.
func (d *Dao) RawCards(c context.Context, mids []int64) (res map[int64]*v1.Card, err error) {
eg, _ := errgroup.WithContext(c)
var medals map[int64]*sml.MedalInfo
eg.Go(func() (e error) {
if medals, e = d.suitRPC.MedalActivatedMulti(c, &sml.ArgMids{Mids: mids}); e != nil {
log.Error("s.suitRPC.MedalActivatedMulti(%v) err %v", mids, e)
e = ecode.Degrade
}
return
})
var blocks map[int64]*bml.RPCResInfo
eg.Go(func() (e error) {
var bs []*bml.RPCResInfo
if bs, e = d.mRPC.BlockBatchInfo(c, &bml.RPCArgBatchInfo{MIDs: mids}); e != nil {
log.Error("d.block.BlockBatchInfo(%v) err %v", mids, e)
e = ecode.Degrade
}
blocks = make(map[int64]*bml.RPCResInfo, len(bs))
for _, block := range bs {
blocks[block.MID] = block
}
return
})
var mbs map[int64]*mml.Member
eg.Go(func() (e error) {
if mbs, e = d.mRPC.Members(c, &mml.ArgMemberMids{Mids: mids}); e != nil {
log.Error("d.mRPC.Members(%v) err(%v)", mids, e)
// e = ecode.Degrade
}
return
})
var vipm map[int64]*v1.VipInfo
eg.Go(func() (e error) {
if vipm, e = d.Vips(c, mids); e != nil {
log.Error("d.CpVips(%v) err(%v)", mids, e)
e = ecode.Degrade
}
return
})
var pendantm map[int64]*sml.PendantEquip
eg.Go(func() (e error) {
if pendantm, e = d.suitRPC.Equipments(c, &sml.ArgEquipments{Mids: mids}); e != nil {
log.Error("d.suitRPC.Equipments(%v) err(%v)", mids, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
res = map[int64]*v1.Card{}
for _, mid := range mids {
card := &v1.Card{Mid: mid}
if mb, ok := mbs[mid]; ok && mb != nil {
card.Name = mb.Name
card.Sign = mb.Sign
card.Sex = mb.SexStr()
card.Rank = int32(mb.Rank)
card.Face = mb.Face
if mb.OfficialInfo != nil {
// card.Official = *mb.OfficialInfo
card.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
card.Level = mb.Cur
} else {
continue
}
if block, ok := blocks[mid]; ok && block != nil {
card.Silence = blockStatusToSilence(block.BlockStatus)
}
if medal, ok := medals[mid]; ok && medal != nil {
card.Nameplate.Nid = int(medal.ID)
card.Nameplate.Name = medal.Name
card.Nameplate.Image = medal.Image
card.Nameplate.ImageSmall = medal.ImageSmall
card.Nameplate.Level = medal.LevelDesc
card.Nameplate.Condition = medal.Condition
}
if vip, ok := vipm[mid]; ok && vip != nil {
card.Vip = *vip
}
if pendant, ok := pendantm[mid]; ok && pendant != nil {
card.Pendant.Pid = int(pendant.Pid)
card.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
card.Pendant.Name = pendant.Pendant.Name
card.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res[mid] = card
}
return
}
// RawProfile get profile by mid.
func (d *Dao) RawProfile(c context.Context, mid int64) (res *v1.Profile, err error) {
eg, _ := errgroup.WithContext(c)
var detail *model.PassportDetail
eg.Go(func() (e error) {
if detail, e = d.PassportDetail(c, mid); e != nil {
log.Error("d.PassPortDetail(%d) err %v", mid, e)
// e = ecode.Degrade
}
return
})
var mb *mml.Member
eg.Go(func() (e error) {
if mb, e = d.mRPC.Member(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
// e = ecode.Degrade
}
return
})
var moral *mml.Moral
eg.Go(func() (e error) {
if moral, e = d.mRPC.Moral(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var realNameStatus *mml.RealnameStatus
eg.Go(func() (e error) {
if realNameStatus, e = d.mRPC.RealnameStatus(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.RealnameStatus(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var medal *sml.MedalInfo
eg.Go(func() (e error) {
if medal, e = d.suitRPC.MedalActivated(c, &sml.ArgMid{Mid: mid}); e != nil {
log.Error("s.suitRPC.MedalActivated(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var block *bml.RPCResInfo
eg.Go(func() (e error) {
if block, e = d.mRPC.BlockInfo(c, &bml.RPCArgInfo{MID: mid}); e != nil {
log.Error("s.dao.BlockInfo(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var vip *v1.VipInfo
eg.Go(func() (e error) {
if vip, e = d.Vip(c, mid); e != nil {
log.Error("d.Vip(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var pendant *sml.PendantEquip
eg.Go(func() (e error) {
if pendant, e = d.suitRPC.Equipment(c, &sml.ArgEquipment{Mid: mid}); e != nil {
log.Error("d.suitRPC.Equipment(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
pfl := &v1.Profile{Mid: mid}
if mb != nil {
pfl.Name = mb.Name
pfl.Sign = mb.Sign
pfl.Sex = mb.SexStr()
pfl.Rank = int32(mb.Rank)
pfl.Face = mb.Face
if mb.OfficialInfo != nil {
// pfl.Official = *mb.OfficialInfo
pfl.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
pfl.Level = mb.Cur
pfl.Birthday = mb.Birthday
}
if block != nil {
pfl.Silence = blockStatusToSilence(block.BlockStatus)
}
if detail != nil {
pfl.JoinTime = int32(detail.JoinTime)
pfl.EmailStatus = bindEmailStatus(detail.Email, detail.Spacesta)
pfl.TelStatus = bindPhoneStatus(detail.Phone)
pfl.IsTourist = boolToInt32(detail.IsTourist)
}
if realNameStatus != nil {
pfl.Identification = identificationStatus(*realNameStatus)
}
pfl.Moral = parseMoral(moral)
if medal != nil {
pfl.Nameplate.Nid = int(medal.ID)
pfl.Nameplate.Name = medal.Name
pfl.Nameplate.Image = medal.Image
pfl.Nameplate.ImageSmall = medal.ImageSmall
pfl.Nameplate.Level = medal.LevelDesc
pfl.Nameplate.Condition = medal.Condition
}
if vip != nil {
pfl.Vip = *vip
}
if pendant != nil {
pfl.Pendant.Pid = int(pendant.Pid)
pfl.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
pfl.Pendant.Name = pendant.Pendant.Name
pfl.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res = pfl
return
}
func blockStatusToSilence(status bml.BlockStatus) int32 {
return boolToInt32(status == bml.BlockStatusForever || status == bml.BlockStatusLimit)
}
func bindEmailStatus(email string, spacesta int8) int32 {
return boolToInt32(spacesta > -10 && len(email) > 0)
}
func bindPhoneStatus(phone string) int32 {
return boolToInt32(len(phone) > 0)
}
func parseMoral(moral *mml.Moral) int32 {
m := int32(mml.DefaultMoral)
if moral != nil {
m = int32(moral.Moral)
}
return m / 100
}
func identificationStatus(realNameStatus mml.RealnameStatus) int32 {
return boolToInt32(realNameStatus == mml.RealnameStatusTrue)
}
func boolToInt32(b bool) int32 {
if b {
return 1
}
return 0
}

View File

@@ -0,0 +1,163 @@
package dao
import (
"context"
"testing"
mml "go-common/app/service/main/member/model"
bml "go-common/app/service/main/member/model/block"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRawInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(110016481)
)
convey.Convey("Get base-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawInfo(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawInfos(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110016811, 110017441}
)
convey.Convey("Batch get base-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawInfos(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(110018101)
)
convey.Convey("Get card-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawCard(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawCards(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110019691, 110019241}
)
convey.Convey("Batch get card-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawCards(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110019691)
)
convey.Convey("Get profile-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawProfile(c, mid)
if err == ecode.Degrade {
err = nil
}
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoblockStatusToSilence(t *testing.T) {
var (
status bml.BlockStatus
)
convey.Convey("Check whether member in block status ", t, func(ctx convey.C) {
p1 := blockStatusToSilence(status)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaobindEmailStatus(t *testing.T) {
var (
email = "zxfd43622@qq.com"
spacesta = int8(0)
)
convey.Convey("Get member bind-email status", t, func(ctx convey.C) {
p1 := bindEmailStatus(email, spacesta)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaobindPhoneStatus(t *testing.T) {
var (
phone = "13849920122"
)
convey.Convey("Get member bind-phone status", t, func(ctx convey.C) {
p1 := bindPhoneStatus(phone)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaoparseMoral(t *testing.T) {
var (
moral = &mml.Moral{
Mid: 3441,
Moral: 7100,
Added: 100,
Deducted: 0,
}
)
convey.Convey("Parse moral value", t, func(ctx convey.C) {
p1 := parseMoral(moral)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoidentificationStatus(t *testing.T) {
var (
realNameStatus = mml.RealnameStatusTrue
)
convey.Convey("Get identification status", t, func(ctx convey.C) {
p1 := identificationStatus(realNameStatus)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, 1)
})
})
}
func TestDaoboolToInt32(t *testing.T) {
var (
b = true
)
convey.Convey("Convert true to int", t, func(ctx convey.C) {
p1 := boolToInt32(b)
ctx.Convey("Then p1 should be 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, 1)
})
})
}

View File

@@ -0,0 +1,16 @@
package dao
import (
"context"
member "go-common/app/service/main/member/model"
)
// RealnameDetail is.
func (d *Dao) RealnameDetail(c context.Context, mid int64) (detail *member.RealnameDetail, err error) {
req := &member.ArgMemberMid{Mid: mid}
if detail, err = d.mRPC.RealnameDetail(c, req); err != nil {
return
}
return
}

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"go-common/app/service/main/account/model"
"github.com/pkg/errors"
)
// MidsByName is.
func (d *Dao) MidsByName(ctx context.Context, names []string) ([]int64, error) {
r := d.es.NewRequest("member_user").
Fields("mid").
Index("user_base").
WhereIn("kwname", names).
Ps(len(names)).
Pn(1)
result := &model.SearchMemberResult{}
if err := r.Scan(ctx, &result); err != nil {
return nil, errors.WithStack(err)
}
return result.Mids(), nil
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoMidsByName(t *testing.T) {
var (
c = context.TODO()
names = []string{"", "一"}
)
convey.Convey("Search mids by name", t, func(ctx convey.C) {
p1, err := d.MidsByName(c, names)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,89 @@
package dao
import (
"context"
"net/url"
v1 "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/net/metadata"
"go-common/library/xstr"
"github.com/pkg/errors"
)
var (
_emptyVipInfos3 = map[int64]*v1.VipInfo{}
)
// RawVip get mid's vip info from account center by vip API.
func (d *Dao) RawVip(c context.Context, mid int64) (vip *v1.VipInfo, err error) {
params := url.Values{}
var res struct {
Code int `json:"code"`
Data struct {
Type int32 `json:"vipType"`
Status int32 `json:"vipStatus"`
DueDate int64 `json:"vipDueDate"`
VipPayType int32 `json:"isAutoRenew"`
} `json:"data"`
}
err = d.httpR.RESTfulGet(c, d.vipInfoURI, metadata.String(c, metadata.RemoteIP), params, &res, mid)
if err != nil {
err = errors.Wrap(err, "dao vip")
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
err = errors.Wrap(err, "dao vip")
return
}
vip = &v1.VipInfo{
Type: res.Data.Type,
Status: res.Data.Status,
DueDate: res.Data.DueDate,
VipPayType: res.Data.VipPayType,
}
return
}
// RawVips get multi mid's vip info from account center by vip API.
func (d *Dao) RawVips(c context.Context, mids []int64) (res map[int64]*v1.VipInfo, err error) {
params := url.Values{}
params.Set("idList", xstr.JoinInts(mids))
var info struct {
Code int `json:"code"`
Data map[int64]*struct {
Type int32 `json:"vipType"`
Status int32 `json:"vipStatus"`
DueDate int64 `json:"vipDueDate"`
} `json:"data"`
}
err = d.httpR.Get(c, d.vipMultiInfoURI, "", params, &info)
if err != nil {
err = errors.Wrap(err, "dao vip")
return
}
if info.Code != 0 {
err = ecode.Int(info.Code)
err = errors.Wrap(err, "dao vip")
return
}
if len(info.Data) == 0 {
res = _emptyVipInfos3
return
}
res = make(map[int64]*v1.VipInfo, len(info.Data))
for mid, v := range info.Data {
if v == nil {
continue
}
vip := &v1.VipInfo{
Type: v.Type,
Status: v.Status,
DueDate: v.DueDate,
}
res[mid] = vip
}
return
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRawVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110018671)
)
convey.Convey("Get vip-info from vip-rpc", t, func(ctx convey.C) {
vip, err := d.RawVip(c, mid)
ctx.Convey("Then err should be nil and vip should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vip, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawVips(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110016841, 110018671}
)
convey.Convey("Batch get vip-infos from vip-rpc", t, func(ctx convey.C) {
res, err := d.RawVips(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}