115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package platformapi
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/fatih/structs"
|
|
|
|
"git.rosy.net.cn/baseapi"
|
|
)
|
|
|
|
const (
|
|
DefClientTimeout = 10 * time.Second
|
|
DefSleepSecondWhenExceedLimit = 6 * time.Second
|
|
DefMaxRecoverableRetryCount = 3
|
|
DefMaxExceedLimitRetryCount = 10
|
|
)
|
|
|
|
type APIRetryConfig struct {
|
|
MaxExceedLimitRetryCount int
|
|
MaxRecoverableRetryCount int
|
|
SleepSecondWhenExceedLimit time.Duration
|
|
}
|
|
|
|
type APIConfig struct {
|
|
APIRetryConfig
|
|
ClientTimeout time.Duration
|
|
}
|
|
|
|
type AccessPlatformAPIWithRetryParam struct {
|
|
APIRetryConfig
|
|
Client *http.Client
|
|
Request *http.Request
|
|
}
|
|
|
|
var (
|
|
DefAPIConfig = APIConfig{
|
|
APIRetryConfig: APIRetryConfig{
|
|
MaxExceedLimitRetryCount: DefMaxExceedLimitRetryCount,
|
|
MaxRecoverableRetryCount: DefMaxRecoverableRetryCount,
|
|
SleepSecondWhenExceedLimit: DefSleepSecondWhenExceedLimit,
|
|
},
|
|
ClientTimeout: DefClientTimeout,
|
|
}
|
|
)
|
|
|
|
const (
|
|
ErrLevelSuccess = "JXC4_SUCCESS"
|
|
ErrLevelExceedLimit = "JXC4_EXCEED_LIMIT"
|
|
ErrLevelRecoverableErr = "JXC4_RECOVERABLE"
|
|
ErrLevelGeneralFail = "JXC4_GENERAL_FAIL"
|
|
ErrLevelCodeIsNotOK = "JXC4_CODE_IS_NOT_OK"
|
|
)
|
|
|
|
// common api access error
|
|
var (
|
|
ErrAPIAccessFailed = errors.New("access API failed")
|
|
ErrHTTPCodeIsNot200 = errors.New("HTTP code is not 200")
|
|
ErrResponseDataFormatWrong = errors.New("the data of response has wrong format")
|
|
)
|
|
|
|
// common callback response
|
|
var (
|
|
ErrStrUnescapeError = "can not unescape data:%v, error:%v"
|
|
ErrStrUnmarshalError = "can not unmarshal data:%v, error:%v"
|
|
ErrStrCallbackSignatureIsWrong = "wrong signature"
|
|
)
|
|
|
|
func init() {
|
|
structs.DefaultTagName = "json"
|
|
}
|
|
|
|
func AccessPlatformAPIWithRetry(client *http.Client, request *http.Request, config *APIConfig, handleResponse func(response *http.Response) (string, error)) error {
|
|
exceedLimitRetryCount := 0
|
|
recoverableErrorRetryCount := 0
|
|
for {
|
|
response, err := client.Do(request)
|
|
if err != nil {
|
|
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err)
|
|
err, ok := err.(net.Error)
|
|
recoverableErrorRetryCount++
|
|
if ok && err.Timeout() && recoverableErrorRetryCount <= config.MaxRecoverableRetryCount {
|
|
continue
|
|
} else {
|
|
baseapi.SugarLogger.Errorf("AccessPlatformAPIWithRetry access api request:%v, error:%v", request, err)
|
|
return ErrAPIAccessFailed
|
|
}
|
|
}
|
|
defer response.Body.Close()
|
|
if response.StatusCode != 200 {
|
|
baseapi.SugarLogger.Errorf("AccessPlatformAPIWithRetry HTTP code is:%d, request:%v", response.StatusCode, request)
|
|
return ErrHTTPCodeIsNot200
|
|
}
|
|
errLevel, err := handleResponse(response)
|
|
if err == nil {
|
|
return nil
|
|
} else if errLevel == ErrLevelExceedLimit {
|
|
exceedLimitRetryCount++
|
|
if exceedLimitRetryCount <= config.MaxExceedLimitRetryCount {
|
|
time.Sleep(config.SleepSecondWhenExceedLimit)
|
|
continue
|
|
}
|
|
} else if errLevel == ErrLevelRecoverableErr {
|
|
recoverableErrorRetryCount++
|
|
if recoverableErrorRetryCount <= config.MaxRecoverableRetryCount {
|
|
continue
|
|
}
|
|
}
|
|
baseapi.SugarLogger.Infof("AccessPlatformAPIWithRetry failed, error:%v", err)
|
|
return err
|
|
}
|
|
}
|