123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package tip
- import (
- "context"
- "crypto/md5"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "net/url"
- "strconv"
- "sync/atomic"
- "time"
- cmcd "go-common/library/ecode"
- "go-common/library/log"
- xhttp "go-common/library/net/http/blademaster"
- xtime "go-common/library/time"
- )
- const (
- _codeOk = 0
- _codeNotModified = -304
- _checkURL = "http://%s/x/v1/msm/codes/2"
- )
- var (
- defualtEcodes = &ecodes{}
- defaultConfig = &Config{
- Domain: "api.bilibili.co",
- All: xtime.Duration(time.Hour),
- Diff: xtime.Duration(time.Minute * 5),
- ClientConfig: &xhttp.ClientConfig{
- App: &xhttp.App{
- Key: "3c4e41f926e51656",
- Secret: "26a2095b60c24154521d24ae62b885bb",
- },
- Dial: xtime.Duration(time.Second),
- Timeout: xtime.Duration(time.Second),
- },
- }
- )
- // Config config.
- type Config struct {
- // Domain server domain
- Domain string
- // All get all time slice
- All xtime.Duration
- // Diff get diff time slice
- Diff xtime.Duration
- //HTTPClient httpclient config
- ClientConfig *xhttp.ClientConfig
- }
- type ecodes struct {
- codes atomic.Value
- client *xhttp.Client
- conf *Config
- }
- type res struct {
- Code int `json:"code"`
- Message string `json:"message"`
- Data *data `json:"data"`
- }
- type data struct {
- Ver int64
- MD5 string
- Code map[int]string
- }
- // Init init ecode.
- func Init(conf *Config) {
- if conf == nil {
- conf = defaultConfig
- } else {
- panic(`请删除配置文件内无用配置!!!perf、log、trace、report、ecode、httpServer
- http://info.bilibili.co/pages/viewpage.action?pageId=3671762
- `)
- }
- defualtEcodes.conf = conf
- defualtEcodes.client = xhttp.NewClient(conf.ClientConfig)
- defualtEcodes.codes.Store(make(map[int]string))
- ver, _ := defualtEcodes.update(0)
- go defualtEcodes.updateproc(ver)
- }
- func (e *ecodes) updateproc(lastVer int64) {
- var (
- ver int64
- err error
- last = time.Now()
- all = time.Duration(e.conf.All)
- diff = time.Duration(e.conf.Diff)
- )
- if e.conf.All == 0 {
- all = time.Hour
- }
- if e.conf.Diff == 0 {
- diff = 5 * time.Minute
- }
- time.Sleep(diff)
- for {
- cur := time.Now()
- if cur.Sub(last) > all {
- if ver, err = e.update(0); err != nil {
- log.Error("e.update() error(%v)", err)
- time.Sleep(10 * time.Second)
- continue
- }
- last = cur
- } else {
- if ver, err = e.update(lastVer); err != nil {
- log.Error("e.update(%d) error(%v)", lastVer, err)
- time.Sleep(10 * time.Second)
- continue
- }
- }
- lastVer = ver
- time.Sleep(diff)
- }
- }
- func (e *ecodes) update(ver int64) (lver int64, err error) {
- var (
- res = &res{}
- bytes []byte
- params = url.Values{}
- )
- params.Set("ver", strconv.FormatInt(ver, 10))
- if err = e.client.Get(context.TODO(), fmt.Sprintf(_checkURL, e.conf.Domain), "", params, &res); err != nil {
- err = fmt.Errorf("e.client.Get(%v) error(%v)", fmt.Sprintf(_checkURL, e.conf.Domain), err)
- return
- }
- switch res.Code {
- case _codeOk:
- if res.Data == nil {
- err = fmt.Errorf("code get() response error result: %v", res)
- return
- }
- case _codeNotModified:
- return ver, nil
- default:
- err = cmcd.Int(res.Code)
- return
- }
- if bytes, err = json.Marshal(res.Data.Code); err != nil {
- return
- }
- mb := md5.Sum(bytes)
- if res.Data.MD5 != hex.EncodeToString(mb[:]) {
- err = fmt.Errorf("get codes fail,error md5")
- return
- }
- oCodes, ok := e.codes.Load().(map[int]string)
- if !ok {
- return
- }
- nCodes := copy(oCodes)
- for k, v := range res.Data.Code {
- nCodes[k] = v
- }
- cmcd.Register(nCodes)
- e.codes.Store(nCodes)
- return res.Data.Ver, nil
- }
- func copy(src map[int]string) (dst map[int]string) {
- dst = make(map[int]string)
- for k1, v1 := range src {
- dst[k1] = v1
- }
- return
- }
|