...

Source file src/github.com/redhat-developer/odo/pkg/task/retry.go

Documentation: github.com/redhat-developer/odo/pkg/task

     1  package task
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"k8s.io/klog"
     8  )
     9  
    10  // Retryable represents a task that can be retried.
    11  type Retryable struct {
    12  	// description of the task
    13  	description string
    14  
    15  	// runner is the actual function that is expected to be retried.
    16  	runner Runner
    17  }
    18  
    19  // Runner is a function that will get invoked via RetryWithSchedule. If exitCondition is false, the function will get invoked again, until
    20  // the given timeout schedule expires. It then returns a result of any type along with a potential error.
    21  type Runner func() (exitCondition bool, result interface{}, err error)
    22  
    23  // NewRetryable creates and returns a new Retryable task.
    24  func NewRetryable(description string, runner Runner) Retryable {
    25  	return Retryable{
    26  		description: description,
    27  		runner:      runner,
    28  	}
    29  }
    30  
    31  // RetryWithSchedule invokes the retryable runner function, and keeps retrying until this runner returns an exitCondition that evaluates to false,
    32  // or the given timeout expires. The timeout schedule can be a seen as a backoff schedule, in the sense that before recalling the runner function,
    33  // RetryWithSchedule waits for each duration defined in the given schedule.
    34  // If the exitCondition is not true after all retries, the behavior is governed by the errorIfTimeout parameter.
    35  // If errorIfTimeout is true, then an error is returned.
    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