2024-11-12 10:08:08 +00:00
|
|
|
package commonUtils
|
2024-11-12 08:10:09 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Retry(
|
|
|
|
ctx context.Context,
|
|
|
|
retryTimes int,
|
|
|
|
waitBeforeRetry time.Duration,
|
|
|
|
exec Task,
|
|
|
|
) (success bool, errs []error) {
|
|
|
|
var err error
|
|
|
|
errs = []error{}
|
|
|
|
for i := 0; i < retryTimes; i++ {
|
|
|
|
if err = exec(ctx); err == nil {
|
|
|
|
return true, errs
|
|
|
|
}
|
|
|
|
errs = append(errs, err)
|
2024-11-12 10:47:58 +00:00
|
|
|
time.Sleep(waitBeforeRetry)
|
2024-11-12 08:10:09 +00:00
|
|
|
}
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
func ExecTask(ctx context.Context, tasks Task) error {
|
|
|
|
errChan := make(chan error)
|
|
|
|
go func() {
|
|
|
|
errChan <- tasks(ctx)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-errChan:
|
|
|
|
return err
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExecTasks Runs each task in a separate goroutine
|
|
|
|
// To set no task timeout -- set taskTimeout to 0
|
|
|
|
func ExecTasks(ctx context.Context, taskTimeout time.Duration, tasks []Task) error {
|
|
|
|
wg := &sync.WaitGroup{}
|
|
|
|
errChan := make(chan error)
|
|
|
|
wgChan := make(chan struct{})
|
|
|
|
|
|
|
|
wg.Add(len(tasks))
|
|
|
|
for i, task := range tasks {
|
|
|
|
go func() {
|
|
|
|
var cancel context.CancelFunc
|
|
|
|
taskCtx := context.Background()
|
|
|
|
if taskTimeout != 0 {
|
|
|
|
taskCtx, cancel = context.WithTimeout(taskCtx, taskTimeout)
|
|
|
|
}
|
|
|
|
if err := task(taskCtx); err != nil {
|
|
|
|
errChan <- errors.Join(fmt.Errorf("error running task %d: ", i), err)
|
|
|
|
}
|
|
|
|
wg.Done()
|
|
|
|
cancel()
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
wg.Wait()
|
|
|
|
close(wgChan)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
case <-wgChan:
|
|
|
|
return nil
|
|
|
|
case err := <-errChan:
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Ternar[T any](condition bool, ifTrue T, ifFalse T) T {
|
|
|
|
if condition {
|
|
|
|
return ifTrue
|
|
|
|
}
|
|
|
|
return ifFalse
|
|
|
|
}
|
|
|
|
|
|
|
|
func Must(err error) {
|
|
|
|
if err != nil {
|
|
|
|
panic(err.Error())
|
|
|
|
}
|
|
|
|
}
|