Files
baseapi/platformapi/platformapi.go
2018-07-22 16:27:21 +08:00

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
}
}