github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/helpers/errors.go (about)

     1  package helpers
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/caos/orbos/mntr"
     9  )
    10  
    11  func Concat(left error, right error) error {
    12  	if left == nil {
    13  		return right
    14  	}
    15  
    16  	if right == nil {
    17  		return left
    18  	}
    19  
    20  	newErr := fmt.Errorf("%s: %s", right.Error(), left.Error())
    21  	if errors.As(left, &mntr.UserError{}) && errors.As(right, &mntr.UserError{}) {
    22  		newErr = mntr.UserError{Err: newErr}
    23  	}
    24  
    25  	return newErr
    26  }
    27  
    28  // Synchronizer implements the error interface as well as
    29  // the Causer interface from package github.com/pkg/errors
    30  // It just returns the first error when Cause is called
    31  //
    32  // It is well suited for scatter and gather synchronization
    33  type Synchronizer struct {
    34  	errors []error
    35  	wg     *sync.WaitGroup
    36  	sync.RWMutex
    37  }
    38  
    39  func (s *Synchronizer) Cause() error {
    40  	return s.errors[0]
    41  }
    42  
    43  func NewSynchronizer(wg *sync.WaitGroup) *Synchronizer {
    44  	return &Synchronizer{errors: make([]error, 0), wg: wg}
    45  }
    46  
    47  func (s *Synchronizer) IsError() bool {
    48  	s.Lock()
    49  	defer s.Unlock()
    50  	return len(s.errors) > 0
    51  }
    52  
    53  func (s *Synchronizer) Done(err error) {
    54  	defer s.wg.Done()
    55  	s.Lock()
    56  	defer s.Unlock()
    57  	if err == nil {
    58  		return
    59  	}
    60  	s.errors = append(s.errors, err)
    61  }
    62  
    63  func (s Synchronizer) Error() string {
    64  	built := ""
    65  	for _, err := range s.errors {
    66  		built = built + ", " + err.Error()
    67  	}
    68  	if len(built) >= 2 {
    69  		built = built[2:]
    70  	}
    71  	return built
    72  }