113 lines
2.8 KiB
Go
113 lines
2.8 KiB
Go
package vidhkwsearcher
|
|
|
|
import (
|
|
"91porn-server/common/constant"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"91porn-server/app/service/searcher"
|
|
"91porn-server/app/service/searcher/vidsearcher"
|
|
"91porn-server/common"
|
|
"91porn-server/common/log"
|
|
"91porn-server/models/s/kwrankmod"
|
|
)
|
|
|
|
// VidHKWSearcher VidHKWSearcher
|
|
type VidHKWSearcher struct {
|
|
uid uint64
|
|
vidOpt searcher.Opter
|
|
}
|
|
|
|
// NewVidHKWSearcher NewVidHKWSearcher
|
|
func NewVidHKWSearcher(uid uint64, vidOpt searcher.Opter) searcher.Searcher {
|
|
return &VidHKWSearcher{
|
|
uid: uid,
|
|
vidOpt: vidOpt,
|
|
}
|
|
}
|
|
|
|
type pair struct {
|
|
Word string
|
|
Result searcher.Resulter
|
|
}
|
|
|
|
const timeout = 3 * time.Second
|
|
const gorouCountMax = 20
|
|
|
|
// Search Search
|
|
func (v *VidHKWSearcher) Search(unuse searcher.KeyWorder, opt searcher.Opter) (result searcher.Resulter, err error) {
|
|
limitEx1 := opt.Limit() + 1
|
|
//获取热词
|
|
words, err := kwrankmod.RecentRanking(limitEx1)
|
|
if err != nil {
|
|
return nil, errors.New("vidhkwsearcher RecentRanking error")
|
|
}
|
|
//没有热词
|
|
if len(words) == 0 {
|
|
return &Result{[]VideoRes{}, false}, nil
|
|
}
|
|
hasNext := false
|
|
if len(words) > int(opt.Limit()) {
|
|
words = words[:opt.Limit()]
|
|
hasNext = true
|
|
}
|
|
gorouCount := opt.Limit()
|
|
if gorouCount > gorouCountMax {
|
|
gorouCount = gorouCountMax
|
|
}
|
|
ch := make(chan pair, gorouCount)
|
|
err_ch := make(chan error)
|
|
for _, w := range words {
|
|
word := w.KeyWord
|
|
common.Go(func() {
|
|
k := &searcher.Keyword{Word: word}
|
|
result, err := vidsearcher.NewVidSearcher(v.uid, constant.SearchSP, 0).Search(k, v.vidOpt)
|
|
if err != nil {
|
|
err_ch <- err
|
|
return
|
|
}
|
|
pair := pair{
|
|
Word: word,
|
|
Result: result,
|
|
}
|
|
ch <- pair
|
|
})
|
|
}
|
|
count := len(words)
|
|
resultMap := make(map[string]searcher.Resulter, count)
|
|
timer := time.NewTimer(timeout)
|
|
for i := 0; i < count; i++ {
|
|
timer.Reset(timeout)
|
|
select {
|
|
case pair := <-ch:
|
|
resultMap[pair.Word] = pair.Result
|
|
if i == count-1 {
|
|
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
|
|
}
|
|
case err := <-err_ch: //获取出错前搜索到的视屏
|
|
log.Error(fmt.Sprintf("VidKWSearcher error:%+v\n", err))
|
|
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
|
|
case <-timer.C: //获取超时前搜索到的视屏
|
|
log.Warn(fmt.Sprintf("VidKWSearcher timeout::%+v\n", timeout))
|
|
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
|
|
}
|
|
}
|
|
return &Result{[]VideoRes{}, false}, nil
|
|
}
|
|
|
|
func toResult(words []kwrankmod.Keyword, vidCountPer int64, resultMap map[string]searcher.Resulter, hasNext bool) searcher.Resulter {
|
|
resList := make([]VideoRes, 0, vidCountPer)
|
|
//还原视屏的排序
|
|
for _, w := range words {
|
|
word := w.KeyWord
|
|
result, ok := resultMap[word]
|
|
if !ok {
|
|
continue
|
|
}
|
|
videoList := result.Data().([]VideoRes)
|
|
resList = append(resList, videoList...)
|
|
}
|
|
return &Result{resList, hasNext}
|
|
}
|