Files
openbilibili/app/service/main/favorite/service/search.go
2019-04-22 20:46:32 +08:00

201 lines
4.7 KiB
Go

package service
import (
"context"
"sort"
"strconv"
"sync"
"go-common/app/service/main/favorite/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// Relations return relations info by fid.
func (s *Service) Relations(c context.Context, typ int8, mid, uid, fid int64, tid, tv, pn, ps int, keyword, order string) (res *model.Favorites, err error) {
if uid > 0 {
mid = uid
}
if order == "" {
order = model.SortMtime
}
res = new(model.Favorites)
res.Page.Num = pn
res.Page.Size = ps
un, err := s.favDao.FavedBit(c, typ, mid)
if err != nil || un {
return
}
folders := make(map[int64]*model.Folder)
if fid == int64(model.AllFidFlag) {
if folders, err = s.userFolders(c, typ, mid); err != nil {
log.Error("s.userFolders(%d,%d) error(%v)", typ, mid, err)
return nil, err
}
} else {
fd, err1 := s.folder(c, typ, mid, fid)
if err1 != nil {
log.Error("s.folder(%d,%d,%d) error(%v)", typ, mid, fid, err1)
return nil, err1
}
folders[fd.ID] = fd
}
var oids []int64
favs := make([]*model.Favorite, 0)
favMap := make(map[int64]*model.Favorite)
if len(folders) == 1 {
for _, f := range folders {
unExpired, err1 := s.favDao.ExpireRelations(c, mid, f.ID)
if err1 != nil {
log.Error("s.favDao.ExpireRelations(%d,%d) error(%v)", mid, f.ID, err1)
return nil, err1
}
if favs, err = s.parRelations(c, typ, mid, f.ID, f.Count, unExpired); err != nil {
return nil, err
}
for _, f := range favs {
oids = append(oids, f.Oid)
favMap[f.Oid] = f
}
}
} else {
var (
fids []int64
okMap map[int64]bool
)
for fid := range folders {
fids = append(fids, fid)
}
if okMap, err = s.favDao.MultiExpireRelations(c, mid, fids); err != nil {
log.Error("s.favDao.MultiExpireRelations(%v,%d) error(%v)", fids, err)
return
}
g := new(errgroup.Group)
mux := new(sync.Mutex)
for _, v := range folders {
f := v
unExpired := okMap[f.ID]
g.Go(func() error {
gfavs, err1 := s.parRelations(c, typ, mid, f.ID, f.Count, unExpired)
if err1 != nil {
log.Error("s.parRelations(%d,%d,%d,%d,%t) error(%v)", typ, mid, f.ID, f.Count, unExpired, err1)
}
mux.Lock()
favs = append(favs, gfavs...)
mux.Unlock()
return nil
})
}
if err = g.Wait(); err != nil {
return
}
sort.Slice(favs, func(i, j int) bool {
return favs[i].MTime < favs[j].MTime
})
ts := make([]*model.Favorite, 0)
for _, f := range favs {
if _, ok := favMap[f.Oid]; ok {
continue
}
ts = append(ts, f)
oids = append(oids, f.Oid)
favMap[f.Oid] = f
}
favs = ts
}
favs = make([]*model.Favorite, 0)
res.List = _emptyFavRelations
if keyword != "" { // riot-search
resp, err1 := s.favDao.SearchArcs(c, keyword, oids, pn, ps)
if err1 != nil || resp == nil {
return res, err1
}
res.Page.Count = resp.Page.Total
for _, oid := range resp.IDs {
if v, ok := favMap[int64(oid)]; ok {
favs = append(favs, v)
}
}
} else { // rank-service
rankPn := pn
rankPs := ps
if order == model.SortMtime {
rankPn = 1
rankPs = len(oids)
}
resp, err1 := s.SortArcsRPC(c, tid, tv, rankPn, rankPs, order, oids)
if err1 != nil || resp == nil {
return res, err1
}
res.Page.Count = resp.Page.Total
for _, oid := range resp.Result {
if v, ok := favMap[oid]; ok {
favs = append(favs, v)
}
}
if order == model.SortMtime {
sort.Slice(favs, func(i, j int) bool {
return favs[i].MTime > favs[j].MTime
})
start := (pn - 1) * ps
end := pn * ps
if start > len(favs) {
res.List = make([]*model.Favorite, 0)
return
}
if end > len(favs) {
end = len(favs)
}
res.List = favs[start:end]
return
}
}
res.List = favs
return
}
// Tlists return lists info by fid.
func (s *Service) Tlists(c context.Context, typ int8, mid, uid, fid int64) (res []*model.Partition, err error) {
if uid > 0 {
mid = uid
}
res = make([]*model.Partition, 0)
un, err := s.favDao.FavedBit(c, typ, mid)
if err != nil || un {
return
}
f, err := s.folder(c, typ, mid, fid)
if err != nil {
log.Error("s.folder(%d,%d,%d) error(%v)", typ, mid, fid, err)
return nil, err
}
var favs []*model.Favorite
unExpired, err := s.favDao.ExpireRelations(c, mid, f.ID)
if err != nil {
log.Error("s.favDao.ExpireRelations(%d,%d) error(%v)", mid, f.ID, err)
return
}
if favs, err = s.parRelations(c, typ, mid, f.ID, f.Count, unExpired); err != nil {
return
}
var oids []int64
for _, fav := range favs {
oids = append(oids, fav.Oid)
}
typeids, err := s.TypeidsRPC(c, oids)
if err != nil || typeids == nil {
return
}
for _, v := range typeids.List {
p := new(model.Partition)
p.Count = v.Count
v, _ := strconv.Atoi(v.Key)
p.Tid = v
res = append(res, p)
}
sort.Slice(res, func(i, j int) bool {
return res[i].Tid < res[j].Tid
})
return
}