316 lines
8.3 KiB
Go
316 lines
8.3 KiB
Go
|
package service
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"go-common/app/admin/main/videoup/model/utils"
|
||
|
"go-common/library/sync/errgroup"
|
||
|
"go-common/library/xstr"
|
||
|
"time"
|
||
|
|
||
|
"go-common/app/admin/main/videoup/model/archive"
|
||
|
accApi "go-common/app/service/main/account/api"
|
||
|
"go-common/library/log"
|
||
|
)
|
||
|
|
||
|
// weightConf 所有激活的配置项
|
||
|
func (s *Service) weightConf(c context.Context) (wconfs map[int8]map[int64]*archive.WCItem, err error) {
|
||
|
items, err := s.arc.WeightConf(c)
|
||
|
if err != nil {
|
||
|
log.Error("WeightConf error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
wconfs = map[int8]map[int64]*archive.WCItem{}
|
||
|
for _, item := range items {
|
||
|
conf, ok := wconfs[item.Radio]
|
||
|
if !ok {
|
||
|
conf = make(map[int64]*archive.WCItem)
|
||
|
}
|
||
|
conf[item.CID] = item
|
||
|
wconfs[item.Radio] = conf
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 同一类型的同id配置只能有一个
|
||
|
func (s *Service) checkConflict(c context.Context, mcases map[int64]*archive.WCItem) (err error) {
|
||
|
wcf, err := s.weightConf(c)
|
||
|
if err != nil {
|
||
|
log.Error("s.weightConf error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
s.twConCache = wcf
|
||
|
for _, item := range mcases {
|
||
|
if cfgs, ok := s.twConCache[item.Radio]; ok {
|
||
|
if cfg, ok := cfgs[item.CID]; ok {
|
||
|
return fmt.Errorf("config(%d) conflict with (id=%d,desc=%s)", item.CID, cfg.ID, cfg.Desc)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// AddWeightConf 配置权重
|
||
|
func (s *Service) AddWeightConf(c context.Context, cfg *archive.WeightConf, uid int64, uname string) (err error) {
|
||
|
//0. 一级分区转化为二级分区
|
||
|
if cfg.Radio == archive.WConfType {
|
||
|
cfg.Ids = s.tarnsType(c, cfg.Ids)
|
||
|
}
|
||
|
|
||
|
//1. 解析表单提交的配置
|
||
|
mcases, istaskid, err := archive.ParseWeightConf(cfg, uid, uname)
|
||
|
if err != nil {
|
||
|
log.Error("archive.ParseWeightConf(%v, %v) error(%v)", cfg, uname, err)
|
||
|
return
|
||
|
}
|
||
|
//2. 检查是否互相冲突
|
||
|
if err = s.checkConflict(c, mcases); err != nil {
|
||
|
log.Error("s.checkConflict error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//3. 更新任务的权重配置
|
||
|
if istaskid {
|
||
|
if err = s.setWeightConf(c, cfg.Ids, mcases); err != nil {
|
||
|
log.Error("s.setWeightConf error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//4. 将配置存储到数据库表
|
||
|
if err = s.arc.InWeightConf(c, mcases); err != nil {
|
||
|
log.Error("s.arc.InWeightConf(%v) error(%v)", mcases, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// DelWeightConf 删除配置项
|
||
|
func (s *Service) DelWeightConf(c context.Context, id int64) (err error) {
|
||
|
if _, err = s.arc.DelWeightConf(c, id); err != nil {
|
||
|
log.Error("s.DelWeightConf(%d) error(%v)", id, err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// ListWeightConf 列出配置
|
||
|
func (s *Service) ListWeightConf(c context.Context, v *archive.Confs) (cfg []*archive.WCItem, err error) {
|
||
|
if cfg, err = s.arc.ListWeightConf(c, v); err != nil {
|
||
|
log.Error("s.ListWeightConf(%+v) error(%v)", v, err)
|
||
|
return
|
||
|
}
|
||
|
// 根据taskid补充filename和title
|
||
|
switch v.Radio {
|
||
|
case archive.WConfMid: // 补充昵称和粉丝数
|
||
|
s.singleIDtoName(c, cfg, func(c context.Context, cid int64) (res []interface{}, err error) {
|
||
|
stat, err := s.profile(c, cid)
|
||
|
if err != nil {
|
||
|
log.Error("s.profile(%d) error(%v)", cid, err)
|
||
|
return
|
||
|
}
|
||
|
res = []interface{}{stat.Profile.Name, stat.Follower}
|
||
|
return
|
||
|
}, false, "CID", "Creator", "Fans")
|
||
|
case archive.WConfTaskID: //补充title和filename
|
||
|
s.mulIDtoName(c, cfg, s.arc.LWConfigHelp, "CID", "FileName", "Title", "Vid")
|
||
|
case archive.WConfType: //补充分区名称
|
||
|
s.singleIDtoName(c, cfg, func(c context.Context, cid int64) (res []interface{}, err error) {
|
||
|
if item, ok := s.typeCache[int16(cid)]; ok {
|
||
|
res = []interface{}{item.Name}
|
||
|
}
|
||
|
return
|
||
|
}, false, "CID", "TypeName")
|
||
|
case archive.WConfUpFrom: //补充投稿来源
|
||
|
s.singleIDtoName(c, cfg, func(c context.Context, cid int64) (res []interface{}, err error) {
|
||
|
res = []interface{}{archive.UpFrom(int8(cid))}
|
||
|
return
|
||
|
}, false, "CID", "UpFrom")
|
||
|
default:
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// ListWeightLogs 权重变更日志
|
||
|
func (s *Service) ListWeightLogs(c context.Context, taskid int64, page int) (cfg []*archive.TaskWeightLog, items int64, err error) {
|
||
|
cfg, err = s.arc.WeightLog(c, taskid)
|
||
|
if err != nil {
|
||
|
log.Info("s.ListWeightLogs(%d) error(%v)", taskid, err)
|
||
|
return
|
||
|
}
|
||
|
cfg, items, err = s.weightLogHelp(c, taskid, cfg, page)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// MaxWeight 当前的权重最大值, 供用户配置做参考
|
||
|
func (s *Service) MaxWeight(c context.Context) (max int64, err error) {
|
||
|
return s.arc.GetMaxWeight(c)
|
||
|
}
|
||
|
|
||
|
// 补充查询日志需要的信息
|
||
|
func (s *Service) weightLogHelp(c context.Context, taskid int64, twl []*archive.TaskWeightLog, page int) (retwl []*archive.TaskWeightLog, items int64, err error) {
|
||
|
var (
|
||
|
mid int64
|
||
|
ps *accApi.ProfileStatReply
|
||
|
name string
|
||
|
fans int
|
||
|
upspecial []int8
|
||
|
)
|
||
|
|
||
|
task, err := s.arc.TaskByID(c, taskid)
|
||
|
if task == nil {
|
||
|
log.Error("s.arc.TaskByID(%d) err(%v)", taskid, err)
|
||
|
return
|
||
|
}
|
||
|
// 1.获取用户信息
|
||
|
items = int64(len(twl))
|
||
|
if items == 0 {
|
||
|
return
|
||
|
}
|
||
|
mid = twl[items-1].Mid
|
||
|
if mid == 0 {
|
||
|
log.Error("weightLogHelp taskid=%d miss mid", taskid)
|
||
|
goto EMPTYMID
|
||
|
}
|
||
|
|
||
|
ps, err = s.profile(c, mid)
|
||
|
if err != nil || ps == nil {
|
||
|
log.Error("can't get Account.Card(%d) err(%v)", mid, err)
|
||
|
err = nil
|
||
|
} else {
|
||
|
name = ps.Profile.Name
|
||
|
fans = int(ps.Follower)
|
||
|
}
|
||
|
|
||
|
upspecial = s.getSpecial(mid)
|
||
|
|
||
|
EMPTYMID:
|
||
|
retwl = []*archive.TaskWeightLog{}
|
||
|
// 反转日志顺序
|
||
|
var count int
|
||
|
for i := len(twl) - 1 - (page-1)*20; i >= 0 && count <= 20; func() { i--; count++ }() {
|
||
|
twl[i].Creator = name
|
||
|
twl[i].UpSpecial = upspecial
|
||
|
twl[i].Fans = int64(fans)
|
||
|
twl[i].Wait = twl[i].Uptime.TimeValue().Sub(task.CTime.TimeValue()).Seconds() * 1000.0
|
||
|
if !task.PTime.TimeValue().IsZero() {
|
||
|
twl[i].Ptime = string(task.PTime)
|
||
|
}
|
||
|
|
||
|
if len(twl[i].CfItems) > 0 {
|
||
|
for _, item := range twl[i].CfItems {
|
||
|
var desc = item.Desc
|
||
|
var v = new(archive.WCItem)
|
||
|
if err = json.Unmarshal([]byte(item.Desc), v); err == nil { //兼容新旧日志格式
|
||
|
desc = v.Desc
|
||
|
}
|
||
|
err = nil
|
||
|
twl[i].Desc += fmt.Sprintf("%s:%s; ", archive.CfWeightDesc(item.Radio), desc)
|
||
|
}
|
||
|
}
|
||
|
retwl = append(retwl, twl[i])
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) getSpecial(mid int64) []int8 {
|
||
|
upspecial := []int8{}
|
||
|
for k, v := range s.upperCache {
|
||
|
if _, ok := v[mid]; ok {
|
||
|
upspecial = append(upspecial, k)
|
||
|
}
|
||
|
}
|
||
|
return upspecial
|
||
|
}
|
||
|
|
||
|
func (s *Service) setWeightConf(c context.Context, ids string, mcases map[int64]*archive.WCItem) (err error) {
|
||
|
var mitems map[int64]*archive.TaskPriority
|
||
|
arrid, _ := xstr.SplitInts(ids)
|
||
|
// 1. 获取旧的配置
|
||
|
if mitems, err = s.getTWCache(c, arrid); err != nil {
|
||
|
log.Error("s.getTWCache(%v) error(%v)", arrid, err)
|
||
|
return
|
||
|
}
|
||
|
if len(mitems) == 0 {
|
||
|
return fmt.Errorf("没有找到任务(%v)", arrid)
|
||
|
}
|
||
|
// 2. 将新加配置加入
|
||
|
for _, item := range mitems {
|
||
|
if one, ok := mcases[item.TaskID]; ok && one != nil {
|
||
|
one.Mtime = utils.NewFormatTime(time.Now())
|
||
|
item.CfItems = append(item.CfItems, one)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 3. 更新配置到redis和数据库
|
||
|
var wg errgroup.Group
|
||
|
wg.Go(func() (err error) {
|
||
|
return s.task.SetWeightRedis(c, mitems)
|
||
|
})
|
||
|
for _, item := range mitems {
|
||
|
var descb []byte
|
||
|
v := item
|
||
|
wg.Go(func() (err error) {
|
||
|
if descb, err = json.Marshal(v.CfItems); err != nil {
|
||
|
return
|
||
|
}
|
||
|
_, err = s.arc.UpCwAfterAdd(c, v.TaskID, string(descb))
|
||
|
return
|
||
|
})
|
||
|
}
|
||
|
err = wg.Wait()
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// ShowWeightVC 展示权重配置值
|
||
|
func (s *Service) ShowWeightVC(c context.Context) (wvc *archive.WeightVC, err error) {
|
||
|
if wvc, err = s.arc.WeightVC(c); err != nil {
|
||
|
log.Error("s.arc.WeightVC error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if wvc == nil {
|
||
|
wvc = archive.WLVConf
|
||
|
s.arc.InWeightVC(c, wvc, "默认权重配置")
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SetWeightVC 设置权重配置
|
||
|
func (s *Service) SetWeightVC(c context.Context, wvc *archive.WeightVC) (err error) {
|
||
|
_, err = s.arc.SetWeightVC(c, wvc, "设置权重配置")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 处理一级分区转二级分区
|
||
|
func (s *Service) tarnsType(c context.Context, ids string) (res string) {
|
||
|
var (
|
||
|
mapNoNeed = make(map[int16]struct{}) // 不需要的一级分区
|
||
|
mapNeed = make(map[int16]struct{}) // 需要的一级分区
|
||
|
idres = []int64{}
|
||
|
)
|
||
|
|
||
|
arrid, _ := xstr.SplitInts(ids)
|
||
|
for _, id := range arrid {
|
||
|
if mod, ok := s.typeCache[int16(id)]; ok {
|
||
|
if mod.PID == 0 {
|
||
|
mapNeed[int16(id)] = struct{}{}
|
||
|
} else {
|
||
|
mapNoNeed[mod.PID] = struct{}{}
|
||
|
idres = append(idres, id)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for k := range mapNoNeed {
|
||
|
delete(mapNeed, k)
|
||
|
}
|
||
|
for k := range mapNeed {
|
||
|
idres = append(idres, s.typeCache2[k]...)
|
||
|
}
|
||
|
|
||
|
return xstr.JoinInts(idres)
|
||
|
}
|