Files
huangguo_server/web/service/prefetch/prefetch.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

152 lines
3.5 KiB
Go

package prefetch
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"sync"
"time"
"91porn-server/common/log"
"91porn-server/models/v/sourcemod"
"91porn-server/models/v/vidmod"
)
var exit = make(chan int)
var wg sync.WaitGroup
var client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 20,
MaxIdleConnsPerHost: 20,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: time.Second,
},
Timeout: 30 * time.Second,
}
const prefetchSubmitUrl = "https://prefetch.csrrz.com/master/submit"
func StartSubmitPrefetch() {
wg.Add(1)
go prefetchLoop()
}
func StopSubmitPrefetch() {
close(exit)
wg.Wait()
}
func prefetchLoop() {
log.Info("cdn预热提交协程启动....")
ticker := time.NewTicker(time.Hour * 12)
temp := make(chan int)
time.AfterFunc(time.Minute*5, func() {
temp <- 1
})
for {
select {
case <-exit:
goto exit
case <-ticker.C:
execute()
case <-temp:
execute()
}
}
exit:
log.Info("cdn预热提交协程退出....")
ticker.Stop()
close(temp)
wg.Done()
}
func execute() {
videoCdn, imgCdn := sourcemod.GetVideoAndImgCdn()
if len(videoCdn) == 0 || len(imgCdn) == 0 {
log.Error("视频或者图片cdn为空,不执行推送")
return
}
page, pageSize := int64(1), int64(1000)
for {
data, err := vidmod.GetManyPrefetchVideos(page, pageSize)
if err != nil {
log.Error("查询预热视频出错", log.Any("page", page), log.Any("pageSize", pageSize), log.E(err))
return
}
fmt.Println("page:", page)
page++
dataLen := len(data)
submitData := &SubmitPrefetch{
M3u8List: make([]string, dataLen),
VideoCdnDomains: videoCdn,
ImageList: make([]string, 0),
ImgCdnDomains: imgCdn,
}
for i, v := range data {
submitData.ImageList = append(submitData.ImageList, v.Images...)
submitData.M3u8List[i] = v.M3u8Url
}
if len(submitData.M3u8List) == 0 && len(submitData.ImageList) == 0 {
return
}
//提交需要缓存的数据到预热中心节点
submit(submitData)
//分页查询到最后数据
if int64(len(data)) < pageSize {
fmt.Println("======end=========")
return
}
}
}
func submit(sp *SubmitPrefetch) {
data, _ := json.Marshal(sp)
url := prefetchSubmitUrl
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil {
log.Error("new http post request failed", log.Any("url", url), log.E(err))
return
}
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
log.Error("submit prefetch httpClient do failed", log.Any("url", url), log.E(err))
return
}
defer resp.Body.Close()
buf, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("submit prefetch read response body failed", log.Any("url", url), log.E(err))
return
}
var result SubmitPrefetchResp
if err = json.Unmarshal(buf, &result); err != nil {
log.Error("submit prefetch Unmarshal failed", log.Any("url", url), log.E(err))
return
}
if result.Code != 200 {
log.Error("submit prefetch response failed", log.Any("url", url), log.Any("response's Code", result.Code), log.E(err))
}
}
type SubmitPrefetch struct {
M3u8List []string `json:"m3u8List"`
VideoCdnDomains []string `json:"videoCdnDomains"`
ImageList []string `json:"imageList"`
ImgCdnDomains []string `json:"imgCdnDomains"`
}
type SubmitPrefetchResp struct {
Code int `json:"code"`
Msg string `json:"msg"`
}