go-common/app/interface/main/dm2/service/dm_seg_v2.go
2019-04-22 18:49:16 +08:00

184 lines
4.2 KiB
Go

package service
import (
"context"
"fmt"
"math"
"strconv"
"sync"
"go-common/app/interface/main/dm2/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// DM dm list.
func (s *Service) DM(c context.Context, tp int32, aid, oid int64) (res *model.DMSeg, err error) {
var (
total, size int64 = 1, model.DefaultVideoEnd
mu sync.Mutex
)
sub, err := s.subject(c, tp, oid)
if err != nil {
return
}
res = &model.DMSeg{Elems: make([]*model.Elem, 0, 2*sub.Maxlimit)}
duration, err := s.videoDuration(c, aid, oid)
if err != nil {
return
}
if duration != 0 {
total = int64(math.Ceil(float64(duration) / float64(model.DefaultPageSize)))
size = model.DefaultPageSize
}
g, ctx := errgroup.WithContext(c)
for i := int64(1); i <= total; i++ {
num := i
g.Go(func() (err error) {
var dmseg *model.DMSeg
if dmseg, err = s.dao.DMSegCache(ctx, tp, oid, total, num); err != nil {
return
}
if dmseg == nil {
ps := (num - 1) * size
pe := num * size
fmt.Println(ps, pe, total, num)
if dmseg, err = s.dmSegV2(ctx, sub, total, num, ps, pe); err != nil {
return
}
}
if dmseg != nil {
mu.Lock()
res.Elems = append(res.Elems, dmseg.Elems...)
mu.Unlock()
}
return
})
}
err = g.Wait()
return
}
// DMSegV2 dm segment new.
func (s *Service) DMSegV2(c context.Context, tp int32, mid, aid, oid, pn int64, plat int32) (res *model.DMSegResp, err error) {
page, err := s.pageinfo(c, tp, aid, oid, pn)
if err != nil {
return
}
ps := (page.Num - 1) * page.Size
pe := page.Num * page.Size
sub, err := s.subject(c, tp, oid)
if err != nil {
return
}
res = &model.DMSegResp{
Flag: model.DefaultFlag,
}
if sub.State == model.SubStateClosed {
return
}
flag, err := s.dao.RecFlag(c, mid, aid, oid, 2*sub.Maxlimit, ps, pe, plat)
if err == nil {
res.Flag = flag
}
dmseg, err := s.dao.DMSegCache(c, tp, oid, page.Total, page.Num)
if err != nil {
return
}
if dmseg != nil {
res.Dms = dmseg.Elems
return
}
if dmseg, err = s.dmSegV2(c, sub, page.Total, page.Num, ps, pe); err != nil {
return
}
res.Dms = dmseg.Elems
s.cache.Do(c, func(ctx context.Context) {
s.dao.SetDMSegCache(ctx, tp, oid, page.Total, page.Num, dmseg) // add mc cache
})
return
}
func (s *Service) dmSegV2(c context.Context, sub *model.Subject, total, num, ps, pe int64) (res *model.DMSeg, err error) {
var (
cache = true
limit = 2 * sub.Maxlimit
dmids = make([]int64, 0, limit)
)
res = &model.DMSeg{Elems: make([]*model.Elem, 0, limit)}
normalIds, err := s.dmNormalIds(c, sub.Type, sub.Oid, total, num, ps, pe, limit)
if err != nil {
return
}
dmids = append(dmids, normalIds...)
if sub.Childpool > 0 {
var subtitleIds []int64
if subtitleIds, err = s.dmSegSubtitlesIds(c, sub.Type, sub.Oid, ps, pe, limit); err != nil {
return
}
dmids = append(dmids, subtitleIds...)
}
if len(dmids) <= 0 {
return
}
elemsCache, missed, err := s.dao.IdxContentCacheV2(c, sub.Type, sub.Oid, dmids)
if err != nil {
missed = dmids
cache = false
} else {
res.Elems = append(res.Elems, elemsCache...)
}
if len(missed) == 0 {
return
}
dms, err := s.dmsSeg(c, sub.Type, sub.Oid, missed)
if err != nil {
return
}
for _, dm := range dms {
if e := dm.ToElem(); e != nil {
res.Elems = append(res.Elems, e)
}
}
if cache && len(dms) > 0 {
s.cache.Do(c, func(ctx context.Context) {
s.dao.AddIdxContentCache(ctx, sub.Type, sub.Oid, dms, false) // add memcache,realname=false
})
}
return
}
// pageinfo get page info of oid.
func (s *Service) pageinfo(c context.Context, tp int32, aid, oid, pn int64) (p *model.Page, err error) {
var duration int64
data, ok := s.localCache[keyDuration(tp, oid)]
if ok {
duration, err = strconv.ParseInt(string(data), 10, 64)
} else {
duration, err = s.videoDuration(c, aid, oid)
}
if err != nil {
return
}
if duration == 0 {
p = &model.Page{
Num: pn,
Size: model.DefaultVideoEnd,
Total: 1,
}
} else {
p = &model.Page{
Num: pn,
Size: model.DefaultPageSize,
Total: int64(math.Ceil(float64(duration) / float64(model.DefaultPageSize))),
}
}
if pn > p.Total {
log.Warn("oid:%d pn:%d larger than total page:%d", oid, pn, p.Total)
err = ecode.NotModified
return
}
return
}