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,105 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"archive_test.go",
"content_ext_test.go",
"databus_test.go",
"log_test.go",
"service_test.go",
"special_permit_test.go",
"up_card_test.go",
"up_data_test.go",
"up_group_test.go",
"up_info_test.go",
"up_switch_test.go",
"up_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/up/api/v1:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"content_ext.go",
"databus.go",
"log.go",
"service.go",
"special_permit.go",
"up.go",
"up_card.go",
"up_data.go",
"up_group.go",
"up_info.go",
"up_switch.go",
],
importpath = "go-common/app/service/main/up/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/videoup/model/archive:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/up/api/v1:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/archive:go_default_library",
"//app/service/main/up/dao/card:go_default_library",
"//app/service/main/up/dao/data:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/dao/manager:go_default_library",
"//app/service/main/up/dao/monitor:go_default_library",
"//app/service/main/up/dao/up:go_default_library",
"//app/service/main/up/model:go_default_library",
"//app/service/main/up/model/data:go_default_library",
"//library/conf/env:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/permit:go_default_library",
"//library/net/http/blademaster/render:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/time: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,671 @@
package service
import (
"context"
arcgrpc "go-common/app/service/main/archive/api"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/time"
"go-common/library/sync/errgroup"
)
// UpArcs upper passed.
func (s *Service) UpArcs(c context.Context, arg *upgrpc.UpArcsReq) (res *upgrpc.UpArcsReply, err error) {
var (
upcnt *upgrpc.UpCountReply
mid = arg.Mid
ps = int(arg.Ps)
pn = int(arg.Pn)
)
res = new(upgrpc.UpArcsReply)
if upcnt, err = s.UpCount(c, &upgrpc.UpCountReq{Mid: mid}); err != nil {
return
}
if upcnt.Count == 0 {
err = ecode.NothingFound
return
}
if pn < 1 {
pn = 1
}
if ps < 1 {
ps = 20
}
var (
start = (pn - 1) * ps
end = start + ps - 1
aids []int64
)
if ok, _ := s.arc.ExpireUpperPassedCache(c, mid); !ok {
var (
alls []int64
ptimes []time.Time
copyrights []int8
)
if alls, ptimes, copyrights, err = s.arc.UpperPassed(c, mid); err != nil {
return
}
if err = s.buildUpperStaff(c, mid, &alls, &ptimes, &copyrights); err != nil {
return
}
length := len(alls)
if length == 0 || length < start {
err = ecode.NothingFound
return
}
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperPassedCache(c, mid, alls, ptimes, copyrights)
})
if length > end+1 {
aids = alls[start : end+1]
} else {
aids = alls[start:]
}
s.pCacheMiss.Add("up_arcs_mid", 1)
} else {
if aids, err = s.arc.UpperPassedCache(c, mid, start, end); err != nil {
return
}
s.pCacheHit.Add("up_arcs_mid", 1)
}
if len(aids) == 0 {
return
}
var am *arcgrpc.ArcsReply
if am, err = global.GetArcClient().Arcs(c, &arcgrpc.ArcsRequest{Aids: aids}); err != nil {
return
}
for _, aid := range aids {
if a, ok := am.Arcs[aid]; ok {
res.Archives = append(res.Archives, a)
}
}
return
}
// UpsArcs get archives by mids.
func (s *Service) UpsArcs(c context.Context, arg *upgrpc.UpsArcsReq) (res *upgrpc.UpsArcsReply, err error) {
var (
cachedUp []int64
missed []int64
mids = arg.Mids
ps = int(arg.Ps)
pn = int(arg.Pn)
)
if pn < 1 {
pn = 1
}
if ps < 1 {
ps = 20
}
res = new(upgrpc.UpsArcsReply)
if cachedUp, missed, err = s.arc.ExpireUppersCountCache(c, mids); err != nil {
return
}
s.pCacheMiss.Add("up_arcs_mid", int64(len(missed)))
s.pCacheHit.Add("up_arcs_mid", int64(len(cachedUp)))
var (
start = (pn - 1) * ps
end = start + ps - 1
cacheAids []int64
cacheM map[int64][]int64
missAids []int64
missM map[int64][]int64
eg errgroup.Group
)
eg.Go(func() (err error) {
if len(cachedUp) == 0 {
return
}
_, err = s.arc.ExpireUppersPassedCache(c, cachedUp)
return
})
eg.Go(func() (err error) {
if len(cachedUp) == 0 {
return
}
if cacheM, err = s.arc.UppersPassedCache(c, cachedUp, start, end); err != nil {
log.Error("s.arc.UppersPassedCache(%+v) error(%+v)", cachedUp, err)
return
}
for _, aids := range cacheM {
if len(aids) > 0 {
cacheAids = append(cacheAids, aids...)
}
}
return
})
eg.Go(func() (err error) {
if len(missed) == 0 {
return
}
var (
ptimeM map[int64][]time.Time // <mid,ptime-list>
copyrightM map[int64][]int8 // <mid,copyright-list>
)
if missM, ptimeM, copyrightM, err = s.arc.UppersPassed(c, missed); err != nil {
log.Error("s.arc.UppersPassed(%+v) error(%+v)", missed, err)
return
}
if err = s.buildUppersStaffs(c, missed, missM, ptimeM, copyrightM); err != nil {
log.Error("s.arc.UppersPassed(%+v,%+v,%+v,%+v) error(%+v)", missed, missM, ptimeM, copyrightM, err)
return
}
for mid, aids := range missM {
length := len(aids)
if length == 0 || length < start {
continue
}
var (
cmid = mid
clength = int64(length)
cptime = ptimeM[mid]
ccopyright = copyrightM[mid]
caids = aids
)
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, cmid, clength)
s.arc.AddUpperPassedCache(c, cmid, caids, cptime, ccopyright)
})
if len(aids) > end+1 {
missM[mid] = aids[start : end+1]
} else {
missM[mid] = aids[start:]
}
missAids = append(missAids, missM[mid]...)
}
for _, mid := range missed {
if _, ok := missM[mid]; !ok {
var cmid = mid
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, cmid, 0)
})
}
}
return
})
if err = eg.Wait(); err != nil {
return
}
var (
allAids = append(cacheAids, missAids...)
am *arcgrpc.ArcsReply
)
if len(allAids) == 0 {
return
}
if am, err = global.GetArcClient().Arcs(c, &arcgrpc.ArcsRequest{Aids: allAids}); err != nil {
return
}
res.Archives = make(map[int64]*upgrpc.UpArcsReply, len(am.Arcs))
s.buildUpArcsReply(cacheM, am, res)
s.buildUpArcsReply(missM, am, res)
return
}
func (s *Service) buildUpArcsReply(ms map[int64][]int64, am *arcgrpc.ArcsReply, ups *upgrpc.UpsArcsReply) {
for mid, aids := range ms {
arcs := &upgrpc.UpArcsReply{
Archives: make([]*arcgrpc.Arc, 0, len(ms)),
}
for _, aid := range aids {
if a, ok := am.Arcs[aid]; ok {
arcs.Archives = append(arcs.Archives, a)
}
}
ups.Archives[mid] = arcs
}
}
// UpCount upper count.
func (s *Service) UpCount(c context.Context, arg *upgrpc.UpCountReq) (res *upgrpc.UpCountReply, err error) {
var mid = arg.Mid
res = new(upgrpc.UpCountReply)
if res.Count, err = s.arc.UpperCountCache(c, mid); err != nil {
return
}
if res.Count > 0 {
return
}
if res.Count, err = s.buildMidCount(c, mid); err != nil {
return
}
s.arc.AddUpperCountCache(c, mid, res.Count)
return
}
// UpsCount uppers count
func (s *Service) UpsCount(c context.Context, arg *upgrpc.UpsCountReq) (res *upgrpc.UpsCountReply, err error) {
var (
missed []int64
mids = arg.Mids
)
res = new(upgrpc.UpsCountReply)
res.Count = make(map[int64]int64, len(mids))
res.Count, missed, _ = s.arc.UppersCountCache(c, mids)
if len(missed) == 0 {
return
}
var missedCnt map[int64]int64 // <mid,count>
if missedCnt, err = s.buildMidCounts(c, missed); err != nil {
return
}
for _, mid := range missed {
res.Count[mid] = missedCnt[mid]
tmid := mid
tcnt := missedCnt[mid]
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, tmid, tcnt)
})
}
return
}
// UpsAidPubTime get aid and pime by mids
func (s *Service) UpsAidPubTime(c context.Context, arg *upgrpc.UpsArcsReq) (res *upgrpc.UpsAidPubTimeReply, err error) {
var (
cachedUp []int64
missed []int64
mids = arg.Mids
ps = int(arg.Ps)
pn = int(arg.Pn)
)
if pn < 1 {
pn = 1
}
if ps < 1 {
ps = 20
}
res = new(upgrpc.UpsAidPubTimeReply)
if cachedUp, missed, err = s.arc.ExpireUppersCountCache(c, mids); err != nil {
return
}
s.pCacheMiss.Add("up_arcs_mid", int64(len(missed)))
s.pCacheHit.Add("up_arcs_mid", int64(len(cachedUp)))
var (
eg errgroup.Group
cacheAidM map[int64][]*model.AidPubTime
missAidM = make(map[int64][]*model.AidPubTime)
start = (pn - 1) * ps
end = start + ps - 1
)
eg.Go(func() (err error) {
if len(cachedUp) == 0 {
return
}
_, err = s.arc.ExpireUppersPassedCache(c, cachedUp)
return
})
eg.Go(func() (err error) {
if len(cachedUp) == 0 {
return
}
if cacheAidM, err = s.arc.UppersPassedCacheWithScore(c, cachedUp, start, end); err != nil {
log.Error("s.arc.UppersPassedCache(%v) error(%v)", cachedUp, err)
return
}
return
})
eg.Go(func() (err error) {
if len(missed) == 0 {
return
}
var (
ptimeM map[int64][]time.Time // <mid,pubdate-list>
missM map[int64][]int64 // <mid,aid-list>
copyrightM map[int64][]int8 // <mid,copyright-list>
)
if missM, ptimeM, copyrightM, err = s.arc.UppersPassed(c, missed); err != nil {
log.Error("s.arc.UppersPassed(%v) error(%v)", missed, err)
return
}
if err = s.buildUppersStaffs(c, missed, missM, ptimeM, copyrightM); err != nil {
log.Error("s.arc.UppersPassed(%+v,%+v,%+v,%+v) error(%+v)", missed, missM, ptimeM, copyrightM, err)
return
}
for mid, aids := range missM {
length := len(aids)
if length == 0 || length < start {
continue
}
var (
cmid = mid
clength = int64(length)
cptime = ptimeM[mid]
ccopyright = copyrightM[mid]
caids = aids
)
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, cmid, clength)
s.arc.AddUpperPassedCache(c, cmid, caids, cptime, ccopyright)
})
if len(aids) > end+1 {
missM[mid] = aids[start : end+1]
} else {
missM[mid] = aids[start:]
}
for i := start; i < len(missM[mid]); i++ {
missAidM[mid] = append(missAidM[mid], &model.AidPubTime{Aid: aids[i], PubDate: time.Time(cptime[i]), Copyright: ccopyright[i]})
}
}
return
})
if err = eg.Wait(); err != nil {
return
}
res.Archives = make(map[int64]*upgrpc.UpAidPubTimeReply, len(mids))
s.buildUpAidPubTimeReply(cacheAidM, res)
s.buildUpAidPubTimeReply(missAidM, res)
return
}
func (s *Service) buildUpAidPubTimeReply(ms map[int64][]*model.AidPubTime, ups *upgrpc.UpsAidPubTimeReply) {
for mid, aps := range ms {
arcs := &upgrpc.UpAidPubTimeReply{
Archives: make([]*upgrpc.AidPubTime, 0, len(ms)),
}
for _, v := range aps {
arcs.Archives = append(arcs.Archives, &upgrpc.AidPubTime{Aid: v.Aid, PubDate: v.PubDate, Copyright: int32(v.Copyright)})
}
ups.Archives[mid] = arcs
}
}
// AddUpPassedCacheByStaff add up passed archive cache by staff.
func (s *Service) AddUpPassedCacheByStaff(c context.Context, arg *upgrpc.UpCacheReq) (res *upgrpc.NoReply, err error) {
var (
count int64
a *arcgrpc.ArcReply
)
res = new(upgrpc.NoReply)
if a, err = global.GetArcClient().Arc(c, &arcgrpc.ArcRequest{Aid: arg.Aid}); err != nil {
return
}
if ok, _ := s.arc.ExpireUpperPassedCache(c, arg.Mid); !ok {
var (
alls []int64
ptimes []time.Time
copyrights []int8
)
if alls, ptimes, copyrights, err = s.arc.UpperPassed(c, arg.Mid); err != nil {
return
}
if err = s.buildUpperStaff(c, arg.Mid, &alls, &ptimes, &copyrights); err != nil {
return
}
if len(alls) != 0 {
s.arc.AddUpperPassedCache(context.Background(), arg.Mid, alls, ptimes, copyrights)
}
count = int64(len(alls))
} else {
if err = s.arc.AddUpperPassedCache(c, arg.Mid, []int64{a.Arc.Aid}, []time.Time{a.Arc.PubDate}, []int8{int8(a.Arc.Copyright)}); err != nil {
return
}
if count, err = s.buildMidCount(c, arg.Mid); err != nil {
return
}
}
s.arc.AddUpperCountCache(c, arg.Mid, count)
return
}
// AddUpPassedCache add up passed archive cache.
func (s *Service) AddUpPassedCache(c context.Context, arg *upgrpc.UpCacheReq) (res *upgrpc.NoReply, err error) {
var (
midsCnt map[int64]int64 // <mid,count>
expireOKs map[int64]bool // <mid,bool>
a *arcgrpc.ArcReply
mids, cacheMids, missMids []int64
)
res = new(upgrpc.NoReply)
if a, err = global.GetArcClient().Arc(c, &arcgrpc.ArcRequest{Aid: arg.Aid}); err != nil {
return
}
if mids, err = s.arc.StaffAid(c, arg.Aid); err != nil {
return
}
mids = append(mids, arg.Mid)
expireOKs, _ = s.arc.ExpireUppersPassedCache(c, mids)
for mid, ok := range expireOKs {
if ok {
cacheMids = append(cacheMids, mid)
} else {
missMids = append(missMids, mid)
}
}
midsCnt = make(map[int64]int64, len(mids))
if len(missMids) != 0 {
var (
ptimeM map[int64][]time.Time // <mid,pubdate-list>
missM map[int64][]int64 // <mid,aid-list>
copyrightM map[int64][]int8 // <mid,copyright-list>
)
if missM, ptimeM, copyrightM, err = s.arc.UppersPassed(c, missMids); err != nil {
return
}
if err = s.buildUppersStaffs(c, missMids, missM, ptimeM, copyrightM); err != nil {
return
}
for mid, aids := range missM {
var (
cmid = mid
clength = int64(len(aids))
caids = aids
cptime = ptimeM[mid]
ccopyright = copyrightM[mid]
)
midsCnt[mid] = clength
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperPassedCache(c, cmid, caids, cptime, ccopyright)
})
}
}
if len(cacheMids) != 0 {
var cntM map[int64]int64
for _, mid := range cacheMids {
var cmid = mid
s.cacheWorker.Do(c, func(c context.Context) {
if err = s.arc.AddUpperPassedCache(c, cmid, []int64{arg.Aid}, []time.Time{a.Arc.PubDate}, []int8{int8(a.Arc.Copyright)}); err != nil {
return
}
})
}
if cntM, err = s.buildMidCounts(c, mids); err != nil {
return
}
for mid, count := range cntM {
midsCnt[mid] = count
}
}
for mid, count := range midsCnt {
var (
cmid = mid
ccount = count
)
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, cmid, ccount)
})
}
return
}
// DelUpPassedCacheByStaff delete up passed archive cache by staff.
func (s *Service) DelUpPassedCacheByStaff(c context.Context, arg *upgrpc.UpCacheReq) (res *upgrpc.NoReply, err error) {
var (
mid = arg.Mid
aid = arg.Aid
)
res = new(upgrpc.NoReply)
if err = s.arc.DelUpperPassedCache(c, mid, aid); err != nil {
return
}
var count int64
if count, err = s.buildMidCount(c, mid); err != nil {
return
}
s.arc.AddUpperCountCache(c, mid, count)
return
}
// DelUpPassedCache delete up passed archive cache.
func (s *Service) DelUpPassedCache(c context.Context, arg *upgrpc.UpCacheReq) (res *upgrpc.NoReply, err error) {
var (
mids []int64
midsCnt map[int64]int64
)
res = new(upgrpc.NoReply)
if mids, err = s.arc.StaffAid(c, arg.Aid); err != nil {
return
}
mids = append(mids, arg.Mid)
for _, mid := range mids {
var cmid = mid
s.cacheWorker.Do(c, func(c context.Context) {
if err = s.arc.DelUpperPassedCache(c, cmid, arg.Aid); err != nil {
return
}
})
}
if midsCnt, err = s.buildMidCounts(c, mids); err != nil {
return
}
for mid, count := range midsCnt {
var (
cmid = mid
ccount = count
)
s.cacheWorker.Do(c, func(c context.Context) {
s.arc.AddUpperCountCache(c, cmid, ccount)
})
}
return
}
func (s *Service) buildUpperStaff(c context.Context, mid int64, aids *[]int64, ptimes *[]time.Time, copyrights *[]int8) (err error) {
var (
staffAlls, staffAids []int64
staffPtimes []time.Time
staffCopyrights []int8
)
if staffAlls, err = s.arc.Staff(c, mid); err != nil {
return
}
if len(staffAlls) == 0 {
return
}
if staffAids, staffPtimes, staffCopyrights, _, err = s.arc.ArcsAids(c, staffAlls); err != nil {
return
}
if len(staffAids) == 0 || len(staffPtimes) == 0 || len(staffCopyrights) == 0 {
return
}
*aids = append(*aids, staffAids...)
*ptimes = append(*ptimes, staffPtimes...)
*copyrights = append(*copyrights, staffCopyrights...)
return
}
func (s *Service) buildUppersStaffs(c context.Context, mids []int64, midM map[int64][]int64, ptimeM map[int64][]time.Time, copyrightM map[int64][]int8) (err error) {
var (
staffAids []int64
staffAidPtimeM map[int64]*model.AidPubTime // <aid,model.AidPubTime>
staffAidM map[int64][]int64 // <mid,aid-list>
)
if staffAidM, err = s.arc.Staffs(c, mids); err != nil {
return
}
if len(staffAidM) == 0 || staffAidM == nil {
return
}
for _, aids := range staffAidM {
staffAids = append(staffAids, aids...)
}
if len(staffAids) == 0 {
return
}
if _, _, _, staffAidPtimeM, err = s.arc.ArcsAids(c, staffAids); err != nil {
return
}
for mid, aids := range staffAidM {
for _, aid := range aids {
if apt, ok := staffAidPtimeM[aid]; ok {
ptimeM[mid] = append(ptimeM[mid], apt.PubDate)
copyrightM[mid] = append(copyrightM[mid], apt.Copyright)
midM[mid] = append(midM[mid], aid)
}
}
}
return
}
func (s *Service) buildMidCount(c context.Context, mid int64) (count int64, err error) {
if count, err = s.arc.UpperCount(c, mid); err != nil {
return
}
var aids, staffAids []int64
if aids, err = s.arc.Staff(c, mid); err != nil {
return
}
if len(aids) == 0 {
return
}
if staffAids, _, _, _, err = s.arc.ArcsAids(c, aids); err != nil {
return
}
count += int64(len(staffAids))
return
}
func (s *Service) buildMidCounts(c context.Context, mids []int64) (midsCnt map[int64]int64, err error) {
if len(mids) == 0 {
return
}
var (
staffAlls, staffAids []int64
aidM map[int64]struct{} // <mid,struct>
staffAidM map[int64][]int64 // <mid,aid-list>
)
midsCnt = make(map[int64]int64, len(mids))
defer func() {
if err == nil {
for _, mid := range mids {
if _, ok := midsCnt[mid]; !ok {
midsCnt[mid] = 0
}
}
}
}()
if midsCnt, err = s.arc.UppersCount(c, mids); err != nil {
return
}
if staffAidM, err = s.arc.Staffs(c, mids); err != nil {
return
}
for _, aids := range staffAidM {
staffAlls = append(staffAlls, aids...)
}
if len(staffAlls) == 0 {
return
}
if staffAids, _, _, _, err = s.arc.ArcsAids(c, staffAlls); err != nil {
return
}
aidM = make(map[int64]struct{}, len(staffAids))
for _, aid := range staffAids {
aidM[aid] = struct{}{}
}
for mid, aids := range staffAidM {
for _, aid := range aids {
if _, ok := aidM[aid]; ok {
midsCnt[mid]++
}
}
}
return
}

View File

@@ -0,0 +1,122 @@
package service
import (
"context"
"testing"
upgrpc "go-common/app/service/main/up/api/v1"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceUpArcs(t *testing.T) {
convey.Convey("UpArcs", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpArcsReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.UpArcs(c, arg)
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 TestServiceUpsArcs(t *testing.T) {
convey.Convey("UpsArcs", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpsArcsReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.UpsArcs(c, arg)
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 TestServiceUpCount(t *testing.T) {
convey.Convey("UpCount", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpCountReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.UpCount(c, arg)
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 TestServiceUpsCount(t *testing.T) {
convey.Convey("UpsCount", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpsCountReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.UpsCount(c, arg)
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 TestServiceUpsAidPubTime(t *testing.T) {
convey.Convey("UpsAidPubTime", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpsArcsReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.UpsAidPubTime(c, arg)
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 TestServiceAddUpPassedCache(t *testing.T) {
convey.Convey("AddUpPassedCache", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpCacheReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.AddUpPassedCache(c, arg)
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 TestServiceDelUpPassedCache(t *testing.T) {
convey.Convey("DelUpPassedCache", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upgrpc.UpCacheReq{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.DelUpPassedCache(c, arg)
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)
})
})
})
}

View File

@@ -0,0 +1,57 @@
package service
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
)
//BmHTTPErrorWithMsg return custom error msg
func BmHTTPErrorWithMsg(c *bm.Context, err error, msg string) {
if c.IsAborted() {
return
}
c.Error = err
bcode := ecode.Cause(err)
if msg == "" {
msg = err.Error()
}
c.Render(http.StatusOK, render.JSON{
Code: bcode.Code(),
Message: msg,
Data: nil,
})
}
//BmGetStringOrDefault get string
func BmGetStringOrDefault(c *bm.Context, key string, defaul string) (value string, exist bool) {
i, exist := c.Get(key)
if !exist {
value = defaul
return
}
value, exist = i.(string)
if !exist {
value = defaul
}
return
}
//BmGetInt64OrDefault get int64
func BmGetInt64OrDefault(c *bm.Context, key string, defaul int64) (value int64, exist bool) {
i, exist := c.Get(key)
if !exist {
value = defaul
return
}
value, exist = i.(int64)
if !exist {
value = defaul
}
return
}

View File

@@ -0,0 +1,58 @@
package service
import (
"testing"
bm "go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceBmHTTPErrorWithMsg(t *testing.T) {
convey.Convey("BmHTTPErrorWithMsg", t, func(ctx convey.C) {
var (
c = &bm.Context{}
err error
msg = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
BmHTTPErrorWithMsg(c, err, msg)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestServiceBmGetStringOrDefault(t *testing.T) {
convey.Convey("BmGetStringOrDefault", t, func(ctx convey.C) {
var (
c = &bm.Context{}
key = ""
defaul = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, exist := BmGetStringOrDefault(c, key, defaul)
ctx.Convey("Then value,exist should not be nil.", func(ctx convey.C) {
ctx.So(exist, convey.ShouldNotBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceBmGetInt64OrDefault(t *testing.T) {
convey.Convey("BmGetInt64OrDefault", t, func(ctx convey.C) {
var (
c = &bm.Context{}
key = ""
defaul = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, exist := BmGetInt64OrDefault(c, key, defaul)
ctx.Convey("Then value,exist should not be nil.", func(ctx convey.C) {
ctx.So(exist, convey.ShouldNotBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,69 @@
package service
import (
"context"
"encoding/json"
"fmt"
"hash/crc32"
"strconv"
"go-common/app/service/main/up/model"
"go-common/library/log"
"go-common/library/queue/databus"
)
func (s *Service) upConsumer() {
defer s.wg.Done()
var (
msgs = s.upSub.Messages()
mid int64
err error
)
if s.c.Env == "pre" {
return
}
log.Info("up-service start consume")
CLOSE:
for msg := range msgs {
if mid, err = strconv.ParseInt(msg.Key, 10, 64); err != nil {
log.Error("up-service strconv.Atoi(%s) error(%v)", msg.Key, err)
}
if s.closeSub {
log.Info("sub close")
break CLOSE
}
s.workerQueue[s.ShardingQueueIndex(mid)] <- msg
}
for _, c := range s.workerQueue {
close(c)
}
}
//ShardingQueueIndex sharding queue index
func (s *Service) ShardingQueueIndex(mid int64) (i int) { ////注使用校验和取模的原因是使得获取的消息均匀散入不同的worker队列中不直接使用模运算的原因,比如5取模加入mid都是5的倍数话全部消息会进入0号worker队列中。
ch := crc32.ChecksumIEEE([]byte(strconv.FormatInt(mid, 10)))
i = int(ch) % s.workerCount
return
}
//Start start queue
func (s *Service) Start(c chan *databus.Message) { //队列消费
defer s.wg.Done()
var ctx = context.Background()
for msg := range c {
m := &model.Msg{}
if err := json.Unmarshal(msg.Value, m); err != nil {
log.Error("up-service json.Unmarshal(%v) error(%v)", string(msg.Value), err)
err = nil
}
if _, err := s.Edit(ctx, m.MID, m.IsAuthor, uint8(m.From)); err != nil {
log.Error("s.Edit(%v,databus) error(%v)", m, err)
err = nil
}
msg.Commit()
s.upMo++
log.Info("up-service upConsumer key(%s)|value(%s)|partition(%d)|offset(%d) commit", msg.Key, msg.Value, msg.Partition, msg.Offset)
<-s.tokenChan
}
fmt.Printf("up-service close s.workerQueue chan(%+v)\n", c)
}

View File

@@ -0,0 +1,46 @@
package service
import (
"testing"
"go-common/library/queue/databus"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceupConsumer(t *testing.T) {
convey.Convey("upConsumer", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
s.upConsumer()
convCtx.Convey("No return values", func(convCtx convey.C) {
})
})
})
}
func TestServiceShardingQueueIndex(t *testing.T) {
convey.Convey("ShardingQueueIndex", t, func(convCtx convey.C) {
var (
mid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
i := s.ShardingQueueIndex(mid)
convCtx.Convey("Then i should not be nil.", func(convCtx convey.C) {
convCtx.So(i, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceStart(t *testing.T) {
convey.Convey("Start", t, func(convCtx convey.C) {
var (
c = make(chan *databus.Message)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
s.Start(c)
convCtx.Convey("No return values", func(convCtx convey.C) {
})
})
})
}

View File

@@ -0,0 +1,82 @@
package service
import (
"context"
"time"
"go-common/app/admin/main/videoup/model/archive"
accgrpc "go-common/app/service/main/account/api"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/queue/databus/report"
)
const (
//ActionAdd add
ActionAdd = "add"
//ActionEdit edit
ActionEdit = "edit"
//ActionDelete delete
ActionDelete = "delete"
)
//UpSpecialLogInfo special log
type UpSpecialLogInfo struct {
Up *model.UpSpecialWithName
UpOld *model.UpSpecialWithName
UID int64
UName string
CTime time.Time
Action string
}
// send to log special up edit
func (s *Service) sendUpSpecialLog(c context.Context, opInfo *UpSpecialLogInfo) (err error) {
logData := &report.ManagerInfo{
Uname: opInfo.UName,
UID: opInfo.UID,
Business: archive.LogClientUp,
Type: int(opInfo.Up.GroupID),
Oid: opInfo.Up.Mid,
Action: opInfo.Action,
Ctime: opInfo.CTime,
Content: map[string]interface{}{
"up": opInfo.Up,
},
}
s.fillGroupInfo(c, opInfo.Up)
if opInfo.Action == ActionEdit {
s.fillGroupInfo(c, opInfo.UpOld)
logData.Content["old_up"] = opInfo.UpOld
}
report.Manager(logData)
log.Info("sendUpSpecialLog logData(%+v) opInfo(%+v)", logData, opInfo)
return
}
func (s *Service) fillGroupInfo(c context.Context, up *model.UpSpecialWithName) {
if up == nil || up.GroupName != "" {
return
}
var (
err error
infosReply *accgrpc.InfoReply
group = s.getGroupCache(up.GroupID)
)
if group != nil {
up.GroupName = group.Name
up.GroupTag = group.Tag
}
if up.Mid == 0 {
return
}
if infosReply, err = global.GetAccClient().Info3(c, &accgrpc.MidReq{Mid: up.Mid, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
return
}
if infosReply == nil || infosReply.Info == nil {
return
}
up.UName = infosReply.Info.Name
}

View File

@@ -0,0 +1,39 @@
package service
import (
"context"
"testing"
"go-common/app/service/main/up/model"
"github.com/smartystreets/goconvey/convey"
)
func TestServicesendUpSpecialLog(t *testing.T) {
convey.Convey("sendUpSpecialLog", t, func(ctx convey.C) {
var (
c = context.Background()
opInfo = &UpSpecialLogInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := s.sendUpSpecialLog(c, opInfo)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestServicefillGroupInfo(t *testing.T) {
convey.Convey("fillGroupInfo", t, func(ctx convey.C) {
var (
c = context.Background()
up = &model.UpSpecialWithName{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
s.fillGroupInfo(c, up)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

View File

@@ -0,0 +1,193 @@
package service
import (
"context"
"sync"
"time"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao/archive"
"go-common/app/service/main/up/dao/card"
"go-common/app/service/main/up/dao/data"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/dao/manager"
"go-common/app/service/main/up/dao/monitor"
"go-common/app/service/main/up/dao/up"
"go-common/library/conf/env"
"go-common/library/log"
"go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
"go-common/library/sync/pipeline/fanout"
)
// Service is service.
type Service struct {
c *conf.Config
// up dao
up *up.Dao
mng *manager.Dao
card *card.Dao
Data *data.Dao
arc *archive.Dao
// monitor
monitor *monitor.Dao
upMo int64
// wait group
wg sync.WaitGroup
// chan for mids
// midsChan chan map[int64]int
//for cache func
missch chan func()
// prom
pCacheHit *prom.Prom
pCacheMiss *prom.Prom
// for schdule consume databus data
upSub *databus.Databus
workerQueue []chan *databus.Message
workerCount int
consumeRate int64
specialDBAddRate int64
tokenChan chan int
specialAddDBLimiter chan int
// permit
authSvr *permit.Permit
permCheckMap map[int64][]blademaster.HandlerFunc
// cache worker
cacheWorker *fanout.Fanout
closeSub bool
spGroupsCache map[int64]*upgrpc.UpGroup
spGroupsMidsCache map[int64][]int64
}
// New is go-common/app/service/videoup service implementation.
func New(c *conf.Config) (s *Service) {
if c.UpSub.SpecialAddDBLimit <= 0 {
c.UpSub.SpecialAddDBLimit = 100
}
global.Init(c)
s = &Service{
c: c,
up: up.New(c),
mng: manager.New(c),
card: card.New(c),
// midsChan: make(chan map[int64]int, c.ChanSize),
missch: make(chan func(), 1024),
pCacheHit: prom.CacheHit,
pCacheMiss: prom.CacheMiss,
Data: data.New(c),
arc: archive.New(c),
//up databus consume.
upSub: databus.New(c.UpSub.Config),
monitor: monitor.New(c),
tokenChan: make(chan int, c.UpSub.ConsumeLimit), //速率缓冲大小控制
specialAddDBLimiter: make(chan int, c.UpSub.SpecialAddDBLimit),
consumeRate: int64(1e9 / c.UpSub.ConsumeLimit), //per second for ConsumeLimit,如果ConsumeLimit1=1则表示1s一个如果ConsumeLimit1=10则表示100ms一个以此类推.
specialDBAddRate: int64(1e9 / c.UpSub.SpecialAddDBLimit),
workerQueue: make([]chan *databus.Message, c.UpSub.RoutineLimit),
workerCount: c.UpSub.RoutineLimit,
// cache worker
cacheWorker: global.GetWorker(),
spGroupsCache: make(map[int64]*upgrpc.UpGroup),
spGroupsMidsCache: make(map[int64][]int64),
}
// s.mng.HTTPClient = s.up.GetHTTPClient()
if c.Consume {
s.wg.Add(1)
go s.upConsumer()
for i := 0; i < s.workerCount; i++ {
c := make(chan *databus.Message)
s.workerQueue[i] = c
s.wg.Add(1)
go s.Start(c)
}
go s.generateToken(time.Duration(s.consumeRate), s.tokenChan)
go s.monitorConsume()
}
go s.generateToken(time.Duration(s.specialDBAddRate), s.specialAddDBLimiter)
s.refreshCache()
go s.cacheproc()
return s
}
func (s *Service) generateToken(duration time.Duration, tokenChan chan int) {
var timer = time.NewTicker(duration)
var token = 0
for range timer.C {
token++
tokenChan <- token
}
}
func (s *Service) refreshCache() {
log.Info("refresh cache")
s.loadUpGroups()
s.loadSpGroupsMids()
}
func (s *Service) cacheproc() {
for {
time.Sleep(5 * time.Minute)
s.refreshCache()
}
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.up.Ping(c); err != nil {
log.Error("up-service s.up.Ping err(%v)", err)
}
if err := s.card.Ping(c); err != nil {
log.Error("up-service s.card.Ping err(%v)", err)
}
return
}
func (s *Service) monitorConsume() {
if env.DeployEnv != env.DeployEnvProd {
return
}
var up int64
tm := time.Duration(s.c.Monitor.IntervalAlarm)
for {
time.Sleep(tm)
if s.upMo-up == 0 {
s.monitor.Send(context.TODO(), s.c.Monitor.UserName, "up-service did not consume within "+tm.String()+" minute, moni url"+s.c.Monitor.Moni)
}
up = s.upMo
}
}
func (s *Service) loadUpGroups() {
ugs, err := s.mng.UpGroups(context.Background())
if err != nil {
log.Error("s.mng.UpGroups error(%v)", err)
return
}
s.spGroupsCache = ugs
}
// Close sub.
func (s *Service) Close() {
s.upSub.Close()
// close(s.midsChan)
s.closeSub = true
time.Sleep(time.Second * 2)
s.mng.Close()
s.up.Close()
s.card.Close()
global.Close()
s.wg.Wait()
}
//SetAuthServer set auth
func (s *Service) SetAuthServer(authSvr *permit.Permit) {
s.authSvr = authSvr
s.permCheckMap = map[int64][]blademaster.HandlerFunc{
15: {
s.authSvr.Permit("PRIORITY_SIGN_UP"),
},
}
}

View File

@@ -0,0 +1,160 @@
package service
import (
"context"
"flag"
"path/filepath"
"strconv"
"testing"
"time"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/model"
"go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
xtime "go-common/library/time"
"github.com/davecgh/go-spew/spew"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
pCfg = &databus.Config{
Key: "4c76cbb7a985ac90",
Secret: "f36fbb15a85c6e21b0ee22a560ef3a67",
Group: "Creative-MainArchive-P",
Topic: "Creative-T",
Action: "pub",
Name: "up-service/pub",
Proto: "tcp",
Addr: "172.16.33.158:6205",
Active: 10,
Idle: 5,
DialTimeout: xtime.Duration(time.Second),
WriteTimeout: xtime.Duration(time.Second),
ReadTimeout: xtime.Duration(time.Second),
IdleTimeout: xtime.Duration(time.Minute),
}
)
func init() {
dir, _ := filepath.Abs("../cmd/up-service.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Attr(t *testing.T) {
mdlUp := &model.Up{
Attribute: 0,
}
Convey("testAttr", t, WithService(func(s *Service) {
Convey("AttrSet", func() {
mdlUp.AttrSet(1, model.AttrArchiveNewUp)
})
Convey("AttrVal", func() {
attr := mdlUp.AttrVal(model.AttrArchiveNewUp)
intAttr := model.InAttr(attr)
spew.Dump(attr, intAttr)
})
}))
}
func Test_service(t *testing.T) {
var (
c = context.Background()
from = uint8(1)
)
Convey("db", t, WithService(func(s *Service) {
Convey("Ping", func() {
s.Ping(context.Background())
})
}))
Convey("up", t, WithService(func(s *Service) {
Convey("AddOrUpdateDB", func() {
_, err := s.Edit(c, int64(2089809), 1, from)
So(err, ShouldBeNil)
})
Convey("Info", func() {
isAuthor, err := s.Info(c, int64(2089809), from)
So(err, ShouldBeNil)
println(isAuthor)
})
}))
Convey("db", t, WithService(func(s *Service) {
Convey("Close", func() {
s.Close()
})
}))
}
//func testSub(t *testing.T, d *databus.Databus) {
// for {
// m, ok := <-d.Messages()
// if !ok {
// return
// }
// t.Logf("sub message: %s", string(m.Value))
// if err := m.Commit(); err != nil {
// t.Errorf("sub commit error(%v)\n", err)
// }
// }
//}
func testPub(t *testing.T, mid int64, from int, isauthor int) {
pub := databus.New(pCfg)
m := &model.Msg{
MID: mid,
From: from,
IsAuthor: isauthor, //偶数=0,基数=1
TimeStamp: time.Now().Unix(),
}
if err := pub.Send(context.Background(), strconv.FormatInt(m.MID, 10), m); err != nil {
t.Errorf("d.Send(test) error(%v)", err)
} else {
t.Logf("pub message %v", m)
}
}
func Test_databus(t *testing.T) {
mid1 := int64(1)
testPub(t, mid1, 0, 1)
testPub(t, mid1, 1, 0)
testPub(t, mid1, 2, 0)
//go testSub(t, s.upSub)
//time.Sleep(time.Second * 3)
//s.upSub.Close()
}
func TestService_SpecialAdd(t *testing.T) {
var (
c = &blademaster.Context{}
)
Convey("service", t, WithService(func(s *Service) {
Convey("SpecialAdd", func() {
var _, e = s.SpecialAdd(c, "", &model.UpSpecial{}, 12345)
So(e, ShouldNotBeNil)
})
}))
}
func TestService_BmGetStringOrDefault(t *testing.T) {
var (
c = &blademaster.Context{}
)
Convey("service", t, WithService(func(s *Service) {
Convey("BmGetStringOrDefault", func() {
var _, ok = BmGetStringOrDefault(c, "t", "default")
So(ok, ShouldBeFalse)
})
}))
}

View File

@@ -0,0 +1,20 @@
package service
import (
"go-common/library/ecode"
"go-common/library/net/http/blademaster"
)
//SpecialGroupPermit check permit for special groups
func (s *Service) SpecialGroupPermit(c *blademaster.Context, groupID int64) (err error) {
if handlerList, ok := s.permCheckMap[groupID]; ok && handlerList != nil {
for _, f := range handlerList {
f(c)
if c.IsAborted() {
err = ecode.AccessDenied
break
}
}
}
return
}

View File

@@ -0,0 +1,24 @@
package service
import (
"testing"
"go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceSpecialGroupPermit(t *testing.T) {
convey.Convey("SpecialGroupPermit", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
groupID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := s.SpecialGroupPermit(c, groupID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,519 @@
package service
import (
"context"
"fmt"
"strconv"
"strings"
"time"
accgrpc "go-common/app/service/main/account/api"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"go-common/library/xstr"
"github.com/pkg/errors"
)
//Edit 处理通过databus注册的up主信息。如果该up曾经注册过则更新attr并更新db否则第一次计算attr并插入db。
func (s *Service) Edit(c context.Context, mid int64, isAuthor int, from uint8) (row int64, err error) {
var res, mdlUp *model.Up
res, err = s.up.RawUp(c, mid) //查询db
if err != nil {
return
}
if res != nil {
mdlUp = &model.Up{MID: res.MID, Attribute: res.Attribute}
} else {
mdlUp = &model.Up{MID: mid}
}
mdlUp.AttrSet(isAuthor, from)
if row, err = s.up.AddUp(c, mdlUp); err != nil {
return
}
if row > 0 {
s.up.DelCpUp(c, mid)
}
return
}
//Info get auth info by mid.
func (s *Service) Info(c context.Context, mid int64, from uint8) (isAuthor int, err error) {
var res *model.Up
if res, err = s.up.Up(c, mid); err != nil {
return
}
if res == nil {
return
}
isAuthor = res.AttrVal(from)
return
}
// UpAttr .
func (s *Service) UpAttr(c context.Context, req *upgrpc.UpAttrReq) (res *upgrpc.UpAttrReply, err error) {
res = new(upgrpc.UpAttrReply)
var up *model.Up
if up, err = s.up.Up(c, req.Mid); err != nil {
return
}
if up == nil {
return
}
res.IsAuthor = uint8(up.AttrVal(req.From))
return
}
// IdentifyAll get all type of uper auth.
func (s *Service) IdentifyAll(c context.Context, mid int64, ip string) (ia *model.IdentifyAll, err error) {
cache := true
if ia, err = s.up.IdentityAllCache(c, mid); err != nil {
s.pCacheMiss.Incr("upinfo_cache")
err = nil
cache = false
} else if ia != nil {
s.pCacheHit.Incr("upinfo_cache")
return
}
s.pCacheMiss.Incr("upinfo_cache")
var (
isArc, isArticle, isPic, isBlink int
)
ia = &model.IdentifyAll{}
if isArc, err = s.Info(c, mid, model.AttrArchiveUp); err == nil && isArc > 0 {
ia.Archive = model.IsUp
}
if isArticle, err = s.up.IsAuthor(c, mid, ip); err == nil && isArticle > 0 {
ia.Article = model.IsUp
}
if isPic, err = s.up.Pic(c, mid, ip); err == nil && isPic > 0 {
ia.Pic = model.IsUp
}
if isBlink, err = s.up.Blink(c, mid, ip); err == nil && isBlink > 0 {
ia.Blink = model.IsUp
}
if cache {
s.cacheWorker.Do(c, func(c context.Context) {
s.up.AddIdentityAllCache(c, mid, ia)
})
}
return
}
// UpsByGroup Flows get group ups list.
func (s *Service) UpsByGroup(c context.Context, group int64) (ups []*model.UpSpecial) {
var mids []int64
if group <= 0 {
for _, v := range s.spGroupsCache {
var ok bool
if mids, ok = s.spGroupsMidsCache[v.ID]; !ok {
continue
}
for _, mid := range mids {
ups = append(ups, &model.UpSpecial{GroupID: v.ID, GroupName: v.Name, GroupTag: v.Tag, Mid: mid, Note: v.Note, FontColor: v.FontColor, BgColor: v.BgColor})
}
}
return
}
var (
mok, gok bool
g *upgrpc.UpGroup
)
if g, gok = s.spGroupsCache[group]; !gok {
return
}
if mids, mok = s.spGroupsMidsCache[group]; !mok {
return
}
for _, mid := range mids {
ups = append(ups, &model.UpSpecial{GroupID: g.ID, GroupName: g.Name, GroupTag: g.Tag, Mid: mid, Note: g.Note, FontColor: g.FontColor, BgColor: g.BgColor})
}
return
}
// SpecialDel id 是数据库主键
func (s *Service) SpecialDel(c *bm.Context, id int64) (affectedRow int64, err error) {
oldUp, err := s.mng.GetSpecialByID(c, id)
if err != nil {
log.Warn("get old up fail from db, id=%d", id)
return
}
if oldUp == nil {
log.Warn("no old up found in db, id=%d", id)
return
}
// 检查是否有特殊权限
err = s.SpecialGroupPermit(c, oldUp.GroupID)
if err != nil {
return
}
res, err2 := s.mng.DelSpecialByID(c, id)
err = err2
if err != nil {
log.Error("fail to delete id, id=%d, err=%v", id, err)
return
}
affectedRow, _ = res.RowsAffected()
if affectedRow > 0 {
var up = *oldUp
var uname, _ = BmGetStringOrDefault(c, "username", "unkown")
var uid, _ = BmGetInt64OrDefault(c, "uid", 0)
var oplog = UpSpecialLogInfo{
Up: &model.UpSpecialWithName{UpSpecial: up},
UID: uid,
UName: uname,
CTime: time.Now(),
Action: ActionDelete,
}
s.sendUpSpecialLog(c, &oplog)
}
log.Info("delete id from ups, id=%d, affected row=%d", id, affectedRow)
return
}
//SpecialAdd add special
func (s *Service) SpecialAdd(c context.Context, adminName string, special *model.UpSpecial, mids ...int64) (affectedRow int64, err error) {
var insertMids []int64
for _, mid := range mids {
<-s.specialAddDBLimiter
// 先获取是否有这个用户
var oldUps, err1 = s.mng.GetSpecialByMidGroup(c, mid, special.GroupID)
if err1 != nil {
log.Error("get up from db fail, err=%v, mid=%d", err1, mid)
continue
}
var up = *special
up.Mid = mid
var oplog = UpSpecialLogInfo{
Up: &model.UpSpecialWithName{UpSpecial: up},
UID: up.UID,
UName: adminName,
CTime: time.Now(),
Action: ActionAdd,
}
// 如果是老用户则记录为edit
if oldUps != nil {
oplog.Action = ActionEdit
oplog.UpOld = &model.UpSpecialWithName{UpSpecial: *oldUps}
}
s.sendUpSpecialLog(c, &oplog)
// 如果有,只是更新一下
if oldUps != nil {
s.mng.UpdateSpecialByID(c, oldUps.ID, special)
log.Info("only update up's info, id=%d, mid=%d", oldUps.ID, mid)
continue
}
// 如果没有,添加一下
insertMids = append(insertMids, mid)
}
// 更新数据库
if len(insertMids) == 0 {
return
}
res, err2 := s.mng.InsertSpecial(c, special, insertMids...)
err = err2
if err != nil {
log.Error("fail to add special ups, err=%v, midscount=%d", err, len(mids))
return
}
affectedRow, _ = res.RowsAffected()
log.Info("insert into ups, affected row=%d, midscount=%d", affectedRow, len(mids))
return
}
//SpecialEdit edit up special
func (s *Service) SpecialEdit(c *bm.Context, special *model.UpSpecial, id int64) (affectedRow int64, err error) {
oldUp, err := s.mng.GetSpecialByID(c, id)
if err != nil {
log.Warn("get old up fail from db, id=%d", id)
return
}
if oldUp == nil {
log.Warn("no old up found in db, id=%d", id)
err = errors.New("up not found in db")
return
}
special.Mid = oldUp.Mid
res, err := s.mng.UpdateSpecialByID(c, id, special)
if err != nil {
log.Error("error update ups, id=%d, info=%v", id, special)
return
}
affectedRow, _ = res.RowsAffected()
log.Info("only update up's info, id=%d, info=%v, rowcount=%d", id, special, affectedRow)
if affectedRow > 0 {
var uname, _ = BmGetStringOrDefault(c, "username", "unkown")
var oplog = UpSpecialLogInfo{
UpOld: &model.UpSpecialWithName{UpSpecial: *oldUp},
Up: &model.UpSpecialWithName{UpSpecial: *special},
UID: special.UID,
UName: uname,
CTime: time.Now(),
Action: ActionEdit,
}
s.sendUpSpecialLog(c, &oplog)
}
return
}
// SpecialGet 这个接口支持更多参数,直接从数据库来查询
func (s *Service) SpecialGet(c *bm.Context, arg *model.GetSpecialArg) (res []*model.UpSpecialWithName, total int, err error) {
var conditions []dao.Condition
var con dao.Condition
//先去查询管理员id
if arg.AdminName != "" {
r, err2 := s.mng.GetUIDByNames(c, []string{arg.AdminName})
err = err2
k, exist := r[arg.AdminName]
if !exist {
err = errors.New("admin name not found")
log.Error("admin name not found, name=%s", arg.AdminName)
return
}
log.Info("get uid by name, name=%s, id=%d", arg.AdminName, k)
arg.UID = int(k)
}
if arg.GroupID != 0 {
con = dao.Condition{
Key: "ups.type",
Operator: "=",
Value: arg.GroupID,
}
conditions = append(conditions, con)
}
if arg.UID != 0 {
con = dao.Condition{
Key: "ups.uid",
Operator: "=",
Value: arg.UID,
}
conditions = append(conditions, con)
}
if arg.FromTime != "" {
con = dao.Condition{
Key: "ups.mtime",
Operator: ">=",
Value: arg.FromTime,
}
conditions = append(conditions, con)
}
if arg.ToTime != "" {
con = dao.Condition{
Key: "ups.mtime",
Operator: "<=",
Value: arg.ToTime,
}
conditions = append(conditions, con)
}
if arg.Mids != "" {
var midstr = strings.Split(arg.Mids, ",")
var mids []int64
for _, v := range midstr {
s, e := strconv.ParseInt(strings.Trim(v, " \n"), 10, 64)
if e != nil {
continue
}
mids = append(mids, s)
}
if len(mids) != 0 {
con = dao.Condition{
Key: "ups.mid",
Operator: " in (" + xstr.JoinInts(mids) + ")",
}
conditions = append(conditions, con)
}
}
conditions = dao.AndCondition(conditions...)
var order = "asc"
if arg.Order == "desc" {
order = arg.Order
}
con = dao.Condition{
Key: "order by ups.mtime",
After: order,
}
conditions = append(conditions, con)
var offset = (arg.Pn - 1) * arg.Ps
var limit = arg.Ps
// 非导出数据时做分页
if arg.Export == "" {
total, err = s.mng.GetSepcialCount(c, conditions...)
if err != nil {
log.Error("get ups count err, err=%v", err)
return
}
conditions = append(conditions,
dao.Condition{Key: fmt.Sprintf("LIMIT %d", limit)},
dao.Condition{Key: fmt.Sprintf("OFFSET %d", offset)},
)
} else {
if arg.Charset == "" {
arg.Charset = "gbk"
}
}
var ups []*model.UpSpecial
ups, err = s.mng.GetSpecial(c, conditions...)
if err != nil {
log.Error("get ups err, err=%v", err)
return
}
// 查询member name
var (
mids, uids []int64
infosReply *accgrpc.InfosReply
uid2NameMap = map[int64]string{}
)
for _, up := range ups {
var upsWithName = &model.UpSpecialWithName{}
upsWithName.Copy(up)
res = append(res, upsWithName)
uids = append(uids, up.UID)
mids = append(mids, up.Mid)
}
if infosReply, err = global.GetAccClient().Infos3(c, &accgrpc.MidsReq{Mids: mids, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
log.Error("global.GetAccClient().Infos3(%+d) error(%+v)", mids, err)
err = nil
}
if len(uids) != 0 {
if uid2NameMap, err = s.mng.GetUNamesByUids(c, uids); err != nil {
log.Error("s.mng.GetUNamesByUids(%+v) err error(%+v)", uids, err)
err = nil
}
}
for _, v := range res {
v.AdminName = uid2NameMap[v.UID]
if infosReply != nil && infosReply.Infos != nil {
if info := infosReply.Infos[v.Mid]; info != nil {
v.UName = info.Name
}
}
}
log.Info("get special, arg=%+v, err=%v", arg, err)
return
}
//ListUpBase list up base info
func (s *Service) ListUpBase(c *bm.Context, size int, lastID int64, activity []int64) (mids []int64, newLastID int64, err error) {
where := ""
if len(activity) > 0 {
where = fmt.Sprintf("AND activity IN (%s)", xstr.JoinInts(activity))
}
var idMids map[int64]int64
if idMids, err = s.card.ListUpBase(c, size, lastID, where); err != nil {
log.Error("fail to list up base info, err=%v", err)
return
}
for id, mid := range idMids {
mids = append(mids, mid)
if id > newLastID {
newLastID = id
}
}
return
}
// UpInfoActivitys up info activity by last_id.
func (s *Service) UpInfoActivitys(c context.Context, req *upgrpc.UpListByLastIDReq) (res *upgrpc.UpActivityListReply, err error) {
var mup map[int64]*upgrpc.UpActivity
res = new(upgrpc.UpActivityListReply)
if mup, err = s.up.UpInfoActivitys(c, req.LastID, req.Ps); err != nil {
return
}
for id, up := range mup {
res.UpActivitys = append(res.UpActivitys, up)
if id > res.LastID {
res.LastID = id
}
}
return
}
//SpecialGetByMid get special
func (s *Service) SpecialGetByMid(c *bm.Context, arg *model.GetSpecialByMidArg) (res []*model.UpSpecial, err error) {
var condition = dao.Condition{
Key: "ups.mid",
Operator: "=",
Value: arg.Mid,
}
res, err = s.mng.GetSpecial(c, condition)
if err != nil {
log.Error("error when get by mid, err=%v", err)
}
log.Info("get special, mid=%d, result=%v", arg.Mid, res)
return
}
// UpSpecial .
func (s *Service) UpSpecial(c context.Context, req *upgrpc.UpSpecialReq) (res *upgrpc.UpSpecialReply, err error) {
res = new(upgrpc.UpSpecialReply)
res.UpSpecial, err = s.mng.UpSpecial(c, req.Mid)
return
}
// UpsSpecial .
func (s *Service) UpsSpecial(c context.Context, req *upgrpc.UpsSpecialReq) (res *upgrpc.UpsSpecialReply, err error) {
res = new(upgrpc.UpsSpecialReply)
res.UpSpecials, err = s.mng.UpsSpecial(c, req.Mids)
return
}
// UpGroupMids .
func (s *Service) UpGroupMids(c context.Context, req *upgrpc.UpGroupMidsReq) (res *upgrpc.UpGroupMidsReply, err error) {
res = new(upgrpc.UpGroupMidsReply)
var (
ok bool
mids []int64
start = (req.Pn - 1) * req.Ps
end = req.Pn * req.Ps
)
if mids, ok = s.spGroupsMidsCache[req.GroupID]; !ok {
return
}
res.Total = len(mids)
switch {
case res.Total <= int(start):
res.Mids = []int64{}
case res.Total <= int(end):
res.Mids = mids[start:]
default:
res.Mids = mids[start:end]
}
return
}

View File

@@ -0,0 +1,204 @@
package service
import (
"context"
accgrpc "go-common/app/service/main/account/api"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/log"
"go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
)
// ListCardBase list card mids
func (s *Service) ListCardBase(ctx *blademaster.Context) (mids []int64, err error) {
mids, err = s.card.ListUpMID(ctx)
return
}
// GetCardInfo get card content by mid
func (s *Service) GetCardInfo(ctx *blademaster.Context, mid int64) (card *model.UpCard, err error) {
cards, err := s.GetCardInfoByMids(ctx, []int64{mid})
if err != nil {
return
}
card = cards[mid]
return
}
// ListCardDetail page list card content
func (s *Service) ListCardDetail(ctx context.Context, offset uint, size uint) (cards map[int64]*model.UpCard, total int, err error) {
cards = make(map[int64]*model.UpCard)
total, err = s.card.CountUpCard(ctx)
if err != nil {
log.Error("ListCardDetail CountUpCard err, err=%v", err)
return
}
if total <= 0 {
return
}
infos, err := s.card.ListUpInfo(ctx, offset, size)
if err != nil {
log.Error("ListCardDetail ListUpInfo err, err=%v", err)
return
}
if len(infos) <= 0 {
return
}
var mids []int64
for _, info := range infos {
mids = append(mids, info.MID)
}
midAccountsMap, err := s.getUpAccountsMap(ctx, mids)
if err != nil {
log.Error("GetCardInfoByMids getUpAccountsMap err, mids=%d, err=%v", mids, err.Error())
return
}
midImagesMap, err := s.card.MidImagesMap(ctx, mids)
if err != nil {
log.Error("card.MidImagesMap err, mids=%d, err=%v", mids, err.Error())
return
}
midVideosMap, err := s.getUpVideosMap(ctx, mids)
if err != nil {
log.Error("GetCardInfoByMids getUpVideosMap err, mids=%d, err=%v", mids, err.Error())
return
}
for _, info := range infos {
card := &model.UpCard{
UpCardInfo: info,
Accounts: []*model.UpCardAccount{},
Images: []*model.UpCardImage{},
Videos: []*model.UpCardVideo{},
}
mid := info.MID
if data, ok := midAccountsMap[mid]; ok {
card.Accounts = data
}
if data, ok := midImagesMap[mid]; ok {
card.Images = data
}
if data, ok := midVideosMap[mid]; ok {
card.Videos = data
}
cards[mid] = card
}
return
}
// GetCardInfoByMids get <mid, card> map by mids
func (s *Service) GetCardInfoByMids(ctx *blademaster.Context, mids []int64) (cards map[int64]*model.UpCard, err error) {
if len(mids) <= 0 {
return
}
cards = make(map[int64]*model.UpCard)
midInfoMap, err := s.card.MidUpInfoMap(ctx, mids)
if err != nil {
log.Error("card.MidUpInfoMap err, mids=%d, err=%v", mids, err.Error())
return
}
midAccountsMap, err := s.getUpAccountsMap(ctx, mids)
if err != nil {
log.Error("GetCardInfoByMids getUpAccountsMap err, mids=%d, err=%v", mids, err.Error())
return
}
midImagesMap, err := s.card.MidImagesMap(ctx, mids)
if err != nil {
log.Error("card.MidImagesMap err, mids=%d, err=%v", mids, err.Error())
return
}
midVideosMap, err := s.getUpVideosMap(ctx, mids)
if err != nil {
log.Error("GetCardInfoByMids getUpVideosMap err, mids=%d, err=%v", mids, err.Error())
return
}
for _, mid := range mids {
card := &model.UpCard{
Accounts: []*model.UpCardAccount{},
Images: []*model.UpCardImage{},
Videos: []*model.UpCardVideo{},
}
if data, ok := midInfoMap[mid]; ok {
card.UpCardInfo = data
}
if data, ok := midAccountsMap[mid]; ok {
card.Accounts = data
}
if data, ok := midImagesMap[mid]; ok {
card.Images = data
}
if data, ok := midVideosMap[mid]; ok {
card.Videos = data
}
cards[mid] = card
}
return
}
func (s *Service) getUpAccountsMap(ctx context.Context, mids []int64) (upAccountsMap map[int64][]*model.UpCardAccount, err error) {
// 全网账号
upAccountsMap, err = s.card.MidAccountsMap(ctx, mids)
if err != nil {
log.Error("card.MidAccountsMap err, mids=%d, err=%v", mids, err)
return
}
var infosReply *accgrpc.InfosReply
if infosReply, err = global.GetAccClient().Infos3(ctx, &accgrpc.MidsReq{Mids: mids, RealIp: metadata.String(ctx, metadata.RemoteIP)}); err != nil {
return
}
if infosReply == nil || infosReply.Infos == nil {
return
}
for mid, info := range infosReply.Infos {
for _, account := range upAccountsMap[mid] {
account.Picture = info.Face
}
}
return
}
func (s *Service) getUpVideosMap(ctx context.Context, mids []int64) (upVideosMap map[int64][]*model.UpCardVideo, err error) {
upVideosMap = make(map[int64][]*model.UpCardVideo)
midAvidsMap, err := s.card.MidAvidsMap(ctx, mids)
if err != nil {
log.Error("card.MidAvidsMap err, mids=%d, err=%v", mids, err.Error())
return
}
var allAvids []int64
for _, avids := range midAvidsMap {
allAvids = append(allAvids, avids...)
}
avidVideoMap, err := s.card.AvidVideoMap(ctx, allAvids)
if err != nil {
log.Error("card.AvidVideoMap err, mids=%d, err=%v", mids, err.Error())
return
}
for mid, avids := range midAvidsMap {
for _, avid := range avids {
if video, ok := avidVideoMap[avid]; ok {
upVideosMap[mid] = append(upVideosMap[mid], video)
}
}
}
return
}

View File

@@ -0,0 +1,106 @@
package service
import (
"testing"
"go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceListCardBase(t *testing.T) {
convey.Convey("ListCardBase", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
var (
c = &blademaster.Context{}
)
mids, err := s.ListCardBase(c)
ctx.Convey("Then err should be nil.mids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(mids, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceGetCardInfo(t *testing.T) {
convey.Convey("GetCardInfo", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
card, err := s.GetCardInfo(c, mid)
ctx.Convey("Then err should be nil.card should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(card, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceListCardDetail(t *testing.T) {
convey.Convey("ListCardDetail", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
offset = uint(0)
size = uint(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cards, total, err := s.ListCardDetail(c, offset, size)
ctx.Convey("Then err should be nil.cards,total should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
ctx.So(cards, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceGetCardInfoByMids(t *testing.T) {
convey.Convey("GetCardInfoByMids", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
mids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cards, err := s.GetCardInfoByMids(c, mids)
ctx.Convey("Then err should be nil.cards should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cards, convey.ShouldNotBeNil)
})
})
})
}
func TestServicegetUpAccountsMap(t *testing.T) {
convey.Convey("getUpAccountsMap", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
mids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
upAccountsMap, err := s.getUpAccountsMap(c, mids)
ctx.Convey("Then err should be nil.upAccountsMap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upAccountsMap, convey.ShouldNotBeNil)
})
})
})
}
func TestServicegetUpVideosMap(t *testing.T) {
convey.Convey("getUpVideosMap", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
mids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
upVideosMap, err := s.getUpVideosMap(c, mids)
ctx.Convey("Then err should be nil.upVideosMap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upVideosMap, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"time"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model/data"
xtime "go-common/library/time"
)
// UpBaseStats .
func (s *Service) UpBaseStats(c context.Context, req *upgrpc.UpStatReq) (res *upgrpc.UpBaseStatReply, err error) {
res = new(upgrpc.UpBaseStatReply)
if req.Date.Time().IsZero() {
// 如果没有填,则取最新的数据,如果有填,则取对应天数的数据,这里不需要做什么操作
// 12点更新数据数据表为昨天日期所以在12点以前要读前天的表
req.Date = xtime.Time(time.Now().Add(-12*time.Hour).AddDate(0, 0, -1).Unix())
}
var stat *data.UpBaseStat
if stat, err = s.Data.BaseUpStat(c, req.Mid, req.Date.Time().Format("20060102")); err != nil {
return
}
stat.CopyToReply(res)
return
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"testing"
upgrpc "go-common/app/service/main/up/api/v1"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceUpBaseStats(t *testing.T) {
convey.Convey("UpBaseStats", t, func(convCtx convey.C) {
var (
c = context.Background()
req = &upgrpc.UpStatReq{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.UpBaseStats(c, req)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,157 @@
package service
import (
"context"
"database/sql"
"strings"
"unicode/utf8"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model"
"go-common/library/log"
"go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
func (s *Service) checkGroupData(arg *model.AddGroupArg) error {
if strings.Trim(arg.Name, " ") == "" || utf8.RuneCountInString(arg.Name) > 15 {
return errors.New("分组名称需在1-15个字符之间")
} else if arg.Tag == "" || utf8.RuneCountInString(arg.Tag) > 10 {
return errors.New("标签名称需在1-10个字符之间")
} else if utf8.RuneCountInString(arg.ShortTag) > 2 {
return errors.New("标签简称需在1-2个字符之间")
} else if utf8.RuneCountInString(arg.Remark) > 50 {
return errors.New("备注不能超过50字符")
}
return nil
}
//AddGroup add group
func (s *Service) AddGroup(c *blademaster.Context, arg *model.AddGroupArg) (result sql.Result, err error) {
if err = s.checkGroupData(arg); err != nil {
log.Error("add group error, %v", err)
return
}
var exist bool
if exist, err = s.mng.CheckGroupExist(c, arg, 0); err != nil {
log.Error("check group exist fail, err=%v, arg=%+v", err, arg)
return
}
if exist {
err = errors.New("该分组、标签或标签简称已存在")
log.Error("group with same name, tag or short_tag exist, arg=%+v", arg)
return
}
result, err = s.mng.AddGroup(c, arg)
if err != nil {
log.Error("add group db error, %v", err)
return
}
return
}
//UpdateGroup update group
func (s *Service) UpdateGroup(c *blademaster.Context, arg *model.EditGroupArg) (result sql.Result, err error) {
if err = s.checkGroupData(arg.AddArg); err != nil {
log.Error("update group error, %v", err)
return
}
var exist bool
if exist, err = s.mng.CheckGroupExist(c, arg.AddArg, arg.ID); err != nil {
log.Error("check group exist fail, err=%v, arg=%+v", err, arg)
return
}
if exist {
err = errors.New("该分组、标签或标签简称已存在")
log.Error("group with same name, tag or short_tag exist, arg=%+v", arg)
return
}
result, err = s.mng.UpdateGroup(c, arg)
if err != nil {
log.Error("update group db error, %v", err)
return
}
return
}
//RemoveGroup remove group
func (s *Service) RemoveGroup(c *blademaster.Context, arg *model.RemoveGroupArg) (result sql.Result, err error) {
result, err = s.mng.RemoveGroup(c, arg)
if err != nil {
log.Error("remove group db error, %v", err)
return
}
return
}
//GetGroup get group
func (s *Service) GetGroup(c *blademaster.Context, arg *model.GetGroupArg) (res []*model.UpGroup, err error) {
return s.mng.GetGroup(c, arg)
}
// getGroupCache get group from cache
func (s *Service) getGroupCache(groupID int64) (group *model.UpGroup) {
if g, ok := s.spGroupsCache[groupID]; ok {
return &model.UpGroup{ID: g.ID, Name: g.Name, Tag: g.Tag, ShortTag: g.ShortTag, Remark: g.Note,
State: 1, FontColor: g.FontColor, BgColor: g.BgColor}
}
return
}
// UpGroups .
func (s *Service) UpGroups(c context.Context, req *upgrpc.NoArgReq) (res *upgrpc.UpGroupsReply, err error) {
res = new(upgrpc.UpGroupsReply)
if len(s.spGroupsCache) > 0 {
res.UpGroups = s.spGroupsCache
}
return
}
func (s *Service) loadSpGroupsMids() {
var (
err error
gids []int64
lastID int64
c = context.Background()
gmap map[int64][]int64
)
for _, v := range s.spGroupsCache {
gids = append(gids, v.ID)
}
gmap = make(map[int64][]int64)
defer func() {
if err == nil {
s.spGroupsMidsCache = gmap
}
}()
for {
var (
lid int64
ps = 10000
gmids map[int64][]int64
)
if lid, gmids, err = s.mng.UpGroupsMids(c, gids, lastID, ps); err != nil {
log.Error("s.mng.UpGroupsMids(%+v,%d,%d)", gids, lastID, ps)
return
}
for _, gid := range gids {
if mids, ok := gmids[gid]; ok {
gmap[gid] = append(gmap[gid], mids...)
}
}
if lid == 0 {
return
}
lastID = lid
}
}

View File

@@ -0,0 +1,120 @@
package service
import (
"context"
"testing"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model"
"go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
func TestServicecheckGroupData(t *testing.T) {
convey.Convey("checkGroupData", t, func(ctx convey.C) {
var (
arg = &model.AddGroupArg{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := s.checkGroupData(arg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestServiceAddGroup(t *testing.T) {
convey.Convey("AddGroup", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
arg = &model.AddGroupArg{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
result, err := s.AddGroup(c, arg)
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 TestServiceUpdateGroup(t *testing.T) {
convey.Convey("UpdateGroup", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
arg = &model.EditGroupArg{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
result, err := s.UpdateGroup(c, arg)
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 TestServiceRemoveGroup(t *testing.T) {
convey.Convey("RemoveGroup", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
arg = &model.RemoveGroupArg{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
result, err := s.RemoveGroup(c, arg)
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 TestServiceGetGroup(t *testing.T) {
convey.Convey("GetGroup", t, func(ctx convey.C) {
var (
c = &blademaster.Context{}
arg = &model.GetGroupArg{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := s.GetGroup(c, arg)
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 TestServiceGetGroupCache(t *testing.T) {
convey.Convey("GetGroupCache", t, func(ctx convey.C) {
var (
groupID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
group := s.getGroupCache(groupID)
ctx.Convey("Then group should not be nil.", func(ctx convey.C) {
ctx.So(group, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceUpGroups(t *testing.T) {
convey.Convey("UpGroups", t, func(convCtx convey.C) {
var (
c = context.Background()
req = &upgrpc.NoArgReq{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.UpGroups(c, req)
convCtx.Convey("No return values", func(convCtx convey.C) {
convCtx.So(res, convey.ShouldNotBeNil)
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,37 @@
package service
import (
"context"
"go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model"
)
// GetUpInfoActive get up info active
func (s *Service) GetUpInfoActive(ctx context.Context, req *model.UpInfoActiveReq) (res *model.UpInfoActiveReply, err error) {
return s.up.UpInfoActive(ctx, req.Mid)
}
// GetUpsInfoActive get ups info active
func (s *Service) GetUpsInfoActive(ctx context.Context, req *model.UpsInfoActiveReq) (res map[int64]*model.UpInfoActiveReply, err error) {
return s.up.UpsInfoActive(ctx, req.Mids)
}
// GetHighAllyUps service get high ally ups
func (s *Service) GetHighAllyUps(ctx context.Context, req *v1.HighAllyUpsReq) (res *v1.HighAllyUpsReply, err error) {
signUps, err := s.up.GetHighAllyUps(ctx, req.Mids)
if err != nil {
return
}
res = new(v1.HighAllyUpsReply)
res.Lists = make(map[int64]*v1.SignUp)
for _, signUp := range signUps {
res.Lists[signUp.Mid] = &v1.SignUp{
Mid: signUp.Mid,
State: int32(signUp.State),
BeginDate: signUp.BeginDate,
EndDate: signUp.EndDate,
}
}
return
}

View File

@@ -0,0 +1,25 @@
package service
import (
"context"
"go-common/app/service/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceGetUpInfoActive(t *testing.T) {
convey.Convey("GetUpInfoActive", t, func(ctx convey.C) {
var (
c = context.Background()
req = &model.UpInfoActiveReq{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.GetUpInfoActive(c, req)
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)
})
})
})
}

View File

@@ -0,0 +1,103 @@
package service
import (
"context"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model"
)
//SetSwitch insert or update switch。
func (s *Service) SetSwitch(c context.Context, mid int64, state int, from uint8) (row int64, err error) {
var res, mdlUp *model.UpSwitch
// 查询db
if res, err = s.up.RawUpSwitch(c, mid); err != nil {
return
}
if res != nil {
mdlUp = &model.UpSwitch{
MID: res.MID,
Attribute: res.Attribute,
}
} else {
mdlUp = &model.UpSwitch{MID: mid}
}
mdlUp.AttrSet(state, from)
if row, err = s.up.SetSwitch(c, mdlUp); err != nil {
return
}
if row > 0 {
s.up.DelCacheUpSwitch(context.Background(), mid)
}
return
}
// SetUpSwitch .
func (s *Service) SetUpSwitch(c context.Context, req *upgrpc.UpSwitchReq) (res *upgrpc.NoReply, err error) {
res = new(upgrpc.NoReply)
var (
row int64
us *model.UpSwitch
)
// 查询db
if us, err = s.up.RawUpSwitch(c, req.Mid); err != nil {
return
}
if us == nil {
us = &model.UpSwitch{MID: req.Mid}
}
us.AttrSet(int(req.State), req.From)
if row, err = s.up.SetSwitch(c, us); err != nil {
return
}
if row > 0 {
s.up.DelCacheUpSwitch(context.Background(), req.Mid)
}
return
}
// UpSwitch for app with cache.
func (s *Service) UpSwitch(c context.Context, req *upgrpc.UpSwitchReq) (res *upgrpc.UpSwitchReply, err error) {
res = new(upgrpc.UpSwitchReply)
var us *model.UpSwitch
if us, err = s.up.UpSwitch(c, req.Mid); err != nil {
return
}
if us == nil {
if req.From == 0 { // 播放器开关,默认为打开
res.State = 1
}
return
}
res.State = uint8(us.AttrVal(req.From))
return
}
//UpSwitchs for app with cache.
func (s *Service) UpSwitchs(c context.Context, mid int64, from uint8) (state int, err error) {
var res *model.UpSwitch
if res, err = s.up.UpSwitch(c, mid); err != nil {
return
}
if res == nil {
if from == 0 { // 播放器开关,默认为打开
state = 1
}
return
}
state = res.AttrVal(from)
return
}
//RawUpSwitch for creative with no cache.
func (s *Service) RawUpSwitch(c context.Context, mid int64, from uint8) (state int, err error) {
var res *model.UpSwitch
if res, err = s.up.RawUpSwitch(c, mid); err != nil {
return
}
if res == nil {
return
}
state = res.AttrVal(from)
return
}

View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceSetSwitch(t *testing.T) {
convey.Convey("SetSwitch", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
state = int(0)
from = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
row, err := s.SetSwitch(c, mid, state, from)
ctx.Convey("Then err should be nil.row should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(row, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceUpSwitch(t *testing.T) {
convey.Convey("UpSwitch", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
from = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
state, err := s.UpSwitchs(c, mid, from)
ctx.Convey("Then err should be nil.state should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(state, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceRawUpSwitch(t *testing.T) {
convey.Convey("RawUpSwitch", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
from = uint8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
state, err := s.RawUpSwitch(c, mid, from)
ctx.Convey("Then err should be nil.state should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(state, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,230 @@
package service
import (
"context"
"testing"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/model"
bm "go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceEdit(t *testing.T) {
convey.Convey("Edit", t, func(convCtx convey.C) {
var (
c = context.Background()
mid = int64(0)
isAuthor = int(0)
from = uint8(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
row, err := s.Edit(c, mid, isAuthor, from)
convCtx.Convey("Then err should be nil.row should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(row, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceInfo(t *testing.T) {
convey.Convey("Info", t, func(convCtx convey.C) {
var (
c = context.Background()
mid = int64(0)
from = uint8(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
isAuthor, err := s.Info(c, mid, from)
convCtx.Convey("Then err should be nil.isAuthor should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(isAuthor, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceIdentifyAll(t *testing.T) {
convey.Convey("IdentifyAll", t, func(convCtx convey.C) {
var (
c = context.Background()
mid = int64(0)
ip = ""
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
ia, err := s.IdentifyAll(c, mid, ip)
convCtx.Convey("Then err should be nil.ia should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(ia, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceUpsByGroup(t *testing.T) {
convey.Convey("UpsByGroup", t, func(convCtx convey.C) {
var (
c = context.Background()
group = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
ups := s.UpsByGroup(c, group)
convCtx.Convey("Then ups should not be nil.", func(convCtx convey.C) {
convCtx.So(ups, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceSpecialDel(t *testing.T) {
convey.Convey("SpecialDel", t, func(convCtx convey.C) {
var (
c = &bm.Context{}
id = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affectedRow, err := s.SpecialDel(c, id)
convCtx.Convey("Then err should be nil.affectedRow should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceSpecialAdd(t *testing.T) {
convey.Convey("SpecialAdd", t, func(convCtx convey.C) {
var (
c = context.Background()
adminName = ""
special = &model.UpSpecial{}
mids = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affectedRow, err := s.SpecialAdd(c, adminName, special, mids)
convCtx.Convey("Then err should be nil.affectedRow should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceSpecialEdit(t *testing.T) {
convey.Convey("SpecialEdit", t, func(convCtx convey.C) {
var (
c = &bm.Context{}
special = &model.UpSpecial{}
id = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affectedRow, err := s.SpecialEdit(c, special, id)
convCtx.Convey("Then err should be nil.affectedRow should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceSpecialGet(t *testing.T) {
convey.Convey("SpecialGet", t, func(convCtx convey.C) {
var (
c = &bm.Context{}
arg = &model.GetSpecialArg{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, total, err := s.SpecialGet(c, arg)
convCtx.Convey("Then err should be nil.res,total should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(total, convey.ShouldNotBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceListUpBase(t *testing.T) {
convey.Convey("ListUpBase", t, func(convCtx convey.C) {
var (
c = &bm.Context{}
size = int(0)
lastID = int64(0)
activity = []int64{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
mids, newLastID, err := s.ListUpBase(c, size, lastID, activity)
convCtx.Convey("Then err should be nil.mids,newLastID should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(newLastID, convey.ShouldNotBeNil)
convCtx.So(mids, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceUpInfoActivitys(t *testing.T) {
convey.Convey("UpInfoActivitys", t, func(convCtx convey.C) {
var (
c = context.Background()
req = &upgrpc.UpListByLastIDReq{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.UpInfoActivitys(c, req)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceSpecialGetByMid(t *testing.T) {
convey.Convey("SpecialGetByMid", t, func(convCtx convey.C) {
var (
c = &bm.Context{}
arg = &model.GetSpecialByMidArg{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.SpecialGetByMid(c, arg)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceUpSpecial(t *testing.T) {
convey.Convey("UpSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
req = &upgrpc.UpSpecialReq{Mid: 27515314}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.UpSpecial(c, req)
convCtx.Convey("No return values", func(convCtx convey.C) {
convCtx.So(res, convey.ShouldNotBeNil)
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestServiceUpsSpecial(t *testing.T) {
convey.Convey("UpsSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
req = &upgrpc.UpsSpecialReq{Mids: []int64{27515314}}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := s.UpsSpecial(c, req)
convCtx.Convey("No return values", func(convCtx convey.C) {
convCtx.So(res, convey.ShouldNotBeNil)
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}