github.com/qiniu/go-sdk/v7@v7.27.0/storage/util.go (about) 1 package storage 2 3 import ( 4 "context" 5 "strings" 6 "time" 7 8 api "github.com/qiniu/go-sdk/v7" 9 "github.com/qiniu/go-sdk/v7/internal/hostprovider" 10 "github.com/qiniu/go-sdk/v7/storagev2/retrier" 11 ) 12 13 func parseEtag(etag string) string { 14 etag = strings.TrimPrefix(etag, "\"") 15 etag = strings.TrimSuffix(etag, "\"") 16 etag = strings.TrimSuffix(etag, ".gz") 17 return etag 18 } 19 20 // ParsePutTime 提供了将PutTime转换为 time.Time 的功能 21 func ParsePutTime(putTime int64) (t time.Time) { 22 t = time.Unix(0, putTime*100) 23 return 24 } 25 26 // IsContextExpired 检查分片上传的ctx是否过期,提前一天让它过期 27 // 因为我们认为如果断点继续上传的话,最长需要1天时间 28 func IsContextExpired(blkPut BlkputRet) bool { 29 if blkPut.Ctx == "" { 30 return false 31 } 32 target := time.Unix(blkPut.ExpiredAt, 0).AddDate(0, 0, -1) 33 now := time.Now() 34 return now.After(target) 35 } 36 37 func isUploadContextExpired(expiredAt int64) bool { 38 target := time.Unix(expiredAt, 0).Add(-2 * time.Hour) 39 return time.Now().After(target) 40 } 41 42 func shouldUploadAgain(err error) bool { 43 if err == nil { 44 return false 45 } 46 47 if isCancelErr(err) { 48 return false 49 } 50 51 switch t := err.(type) { 52 case *ErrorInfo: 53 // 4xx 不重试 54 return t.Code < 400 || t.Code > 499 55 case *api.QError: 56 return t.Code == ErrMaxUpRetry 57 default: 58 // 网络异常可重试 59 return shouldUploadRetryWithOtherHost(err) 60 } 61 } 62 63 func isContextExpiredError(err error) bool { 64 if err == nil { 65 return false 66 } 67 68 errInfo, ok := err.(*ErrorInfo) 69 if !ok { 70 return false 71 } 72 73 return errInfo.Code == 701 || (errInfo.Code == 612 && strings.Contains(errInfo.Error(), "no such uploadId")) 74 } 75 76 func shouldUploadRetryWithOtherHost(err error) bool { 77 return retrier.IsErrorRetryable(err) 78 } 79 80 func doUploadAction(hostProvider hostprovider.HostProvider, retryMax int, freezeDuration time.Duration, action func(host string) error) error { 81 for { 82 host, err := hostProvider.Provider() 83 if err != nil { 84 return api.NewError(ErrMaxUpRetry, err.Error()) 85 } 86 87 for i := 0; ; i++ { 88 err = action(host) 89 90 // 请求成功 91 if err == nil { 92 return nil 93 } 94 95 // 不可重试错误 96 if !shouldUploadRetryWithOtherHost(err) { 97 return err 98 } 99 100 // 超过重试次数退出 101 if i >= retryMax { 102 break 103 } 104 } 105 106 // 单个 host 失败,冻结此 host,换其他 host 107 _ = hostProvider.Freeze(host, err, freezeDuration) 108 } 109 } 110 111 func isCancelErr(err error) bool { 112 if err == context.Canceled { 113 return true 114 } 115 116 if err == nil { 117 return false 118 } 119 120 return strings.Contains(err.Error(), "context canceled") 121 }