Files

136 lines
3.2 KiB
Go

package dataReport
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"sync"
"time"
"videoweb/pub/common/log"
"videoweb/pub/redis"
"github.com/robfig/cron/v3"
)
const (
sdkConfigAPIProd = "https://api.dc-server.cc/sdk/getAvailableDomainList"
sdkConfigAPIDev = "https://dcapi.dc-dev.cc/sdk/getAvailableDomainList"
sdkConfigCacheKey = "report:sdk:domain_config"
sdkConfigCacheTTL = 30 * time.Minute
sdkConfigFetchInterval = "0 */10 * * * *"
)
var (
sdkConfigAPIURL = sdkConfigAPIProd // 默认正式环境,Init时会根据RunMod覆盖
sdkConfigCron *cron.Cron
sdkConfigOnce sync.Once
sdkConfigMu sync.RWMutex
sdkDomainConfig string
sdkConfigUpdatedAt time.Time
)
type sdkConfigResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data string `json:"data"`
}
// StartSDKConfigCron 定时拉取 SDK 域名配置串,服务端只缓存并原样透传。
func StartSDKConfigCron() {
if !Enabled() {
log.Info("dataReport disabled, skip SDK config cron")
return
}
sdkConfigOnce.Do(func() {
if err := RefreshSDKDomainConfig(); err != nil {
log.Error("RefreshSDKDomainConfig first run fail", log.E(err))
}
sdkConfigCron = cron.New(cron.WithSeconds())
if _, err := sdkConfigCron.AddFunc(sdkConfigFetchInterval, func() {
if err := RefreshSDKDomainConfig(); err != nil {
log.Error("RefreshSDKDomainConfig cron fail", log.E(err))
}
}); err != nil {
log.Error("StartSDKConfigCron AddFunc fail", log.E(err))
return
}
sdkConfigCron.Start()
})
}
func StopSDKConfigCron() {
if sdkConfigCron == nil {
return
}
ctx := sdkConfigCron.Stop()
<-ctx.Done()
}
func RefreshSDKDomainConfig() error {
data, err := fetchSDKDomainConfig(sdkConfigAPIURL, &http.Client{Timeout: 5 * time.Second})
if err != nil {
return err
}
setSDKDomainConfig(data)
if redis.Client() == nil {
return nil
}
return redis.Set(sdkConfigCacheKey, data, sdkConfigCacheTTL)
}
func GetSDKDomainConfig() string {
if redis.Client() != nil {
data, err := redis.Get(sdkConfigCacheKey)
if err != nil {
log.Error("GetSDKDomainConfig redis get fail", log.E(err))
} else if data != nil && *data != "" {
setSDKDomainConfig(*data)
return *data
}
}
sdkConfigMu.RLock()
defer sdkConfigMu.RUnlock()
return sdkDomainConfig
}
func setSDKDomainConfig(data string) {
sdkConfigMu.Lock()
defer sdkConfigMu.Unlock()
sdkDomainConfig = data
sdkConfigUpdatedAt = time.Now()
}
func fetchSDKDomainConfig(apiURL string, client *http.Client) (string, error) {
req, err := http.NewRequest(http.MethodGet, apiURL, nil)
if err != nil {
return "", err
}
req.Header.Set("Accept", "application/json")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("sdk config http status: %d", resp.StatusCode)
}
var result sdkConfigResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return "", err
}
if result.Code != 0 {
return "", fmt.Errorf("sdk config code: %d, msg: %s", result.Code, result.Msg)
}
if strings.TrimSpace(result.Data) == "" {
return "", fmt.Errorf("sdk config data is empty")
}
return result.Data, nil
}