...
1 package task
2
3 import (
4 "fmt"
5 "time"
6
7 "k8s.io/klog"
8 )
9
10
11 type Retryable struct {
12
13 description string
14
15
16 runner Runner
17 }
18
19
20
21 type Runner func() (exitCondition bool, result interface{}, err error)
22
23
24 func NewRetryable(description string, runner Runner) Retryable {
25 return Retryable{
26 description: description,
27 runner: runner,
28 }
29 }
30
31
32
33
34
35
36 func (r Retryable) RetryWithSchedule(schedule []time.Duration, errorIfTimeout bool) (interface{}, error) {
37 var err error
38 var result interface{}
39 if len(schedule) == 0 {
40 _, result, err = r.runner()
41 return result, err
42 }
43
44 var exitCondition bool
45 var totalWaitTime float64
46 for _, s := range schedule {
47 seconds := s.Seconds()
48 klog.V(3).Infof("waiting for %0.f second(s) before trying task %q", seconds, r.description)
49 time.Sleep(s)
50 totalWaitTime += seconds
51 exitCondition, result, err = r.runner()
52 if exitCondition {
53 break
54 }
55 }
56
57 if !exitCondition {
58 msg := "aborted retrying task %q which is still not ok after %0.f second(s)"
59 if errorIfTimeout {
60 if err != nil {
61 return result, fmt.Errorf(msg+": %w", r.description, totalWaitTime, err)
62 }
63 return result, fmt.Errorf(msg, r.description, totalWaitTime)
64 }
65 klog.V(3).Infof(msg, r.description, totalWaitTime)
66 }
67
68 return result, err
69 }
70
View as plain text