Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

79 řádky
1.9 KiB

  1. package retry
  2. import (
  3. "fmt"
  4. "gitlab.ecloud.com/ecloud/ecloudsdkcore/errs"
  5. "time"
  6. )
  7. type Template struct {
  8. RetryPolicy Policy
  9. RetryTimes int32
  10. MaxDuringTime int64
  11. }
  12. type RetryError struct {
  13. *errs.SdkError
  14. NumberOfFailedAttempts int32
  15. MaxDuringTimeOfFailedAttempts int64
  16. LastFailedRetryContext Context
  17. }
  18. func NewRetryError(numberOfFailedAttempts int32, maxDuringTimeOfFailedAttempts int64, lastFailedRetryContext Context) *RetryError {
  19. var msg string
  20. if numberOfFailedAttempts > 0 {
  21. msg = fmt.Sprintf("Retrying failed to complete successfully after %v attempts.", numberOfFailedAttempts)
  22. }
  23. if maxDuringTimeOfFailedAttempts > 0 {
  24. msg = fmt.Sprintf("Retrying failed to complete successfully after %v milliseconds.", maxDuringTimeOfFailedAttempts)
  25. }
  26. var retryErr error
  27. if v, err := lastFailedRetryContext.(*ErrorContext); err {
  28. retryErr = v.Err
  29. } else {
  30. retryErr = nil
  31. }
  32. return &RetryError{
  33. SdkError: errs.NewSdkError("RetryError", msg, retryErr),
  34. }
  35. }
  36. type ReFunc func() (interface{}, error)
  37. func (t *Template) Call(f ReFunc) (interface{}, error) {
  38. startTime := time.Now().UnixNano()
  39. for retryTimes := 1; ; retryTimes++ {
  40. var ctx Context
  41. res, err := f()
  42. duration := (time.Now().UnixNano() - startTime) / 1e6
  43. if err != nil {
  44. ctx = &ErrorContext{
  45. Err: err,
  46. RetryTimes: int32(retryTimes),
  47. DelayTime: duration,
  48. }
  49. } else {
  50. ctx = &ResultContext{
  51. Result: res,
  52. RetryTimes: int32(retryTimes),
  53. DelayTime: duration,
  54. }
  55. }
  56. if r, err := ctx.(*ResultContext); err {
  57. return r.Result, nil
  58. }
  59. if int32(retryTimes) == t.RetryTimes {
  60. return nil, NewRetryError(int32(retryTimes), 0, ctx)
  61. } else if duration >= t.MaxDuringTime {
  62. return nil, NewRetryError(int32(retryTimes), duration, ctx)
  63. } else {
  64. sleepTime := t.RetryPolicy.computeWaitTime(ctx)
  65. if sleepTime <= 0 {
  66. continue
  67. }
  68. time.Sleep(time.Duration(sleepTime * 1e6))
  69. }
  70. }
  71. }