Bluemage/go/pkg/errs/multi.go

85 lines
1.5 KiB
Go
Raw Normal View History

2024-08-12 22:00:21 +07:00
package errs
import (
"log/slog"
"strconv"
"strings"
"sync"
)
type Multi []error
func (mu Multi) LogValue() slog.Value {
vals := make([]slog.Attr, len(mu))
for i, e := range mu {
vals[i] = slog.Any(strconv.Itoa(i+1), e)
}
return slog.GroupValue(vals...)
}
func (mu Multi) Error() string {
s := strings.Builder{}
for i, err := range mu.Clean() {
if i > 0 {
s.WriteString("; ")
}
s.WriteString(strconv.Itoa(i + 1))
s.WriteString(". ")
s.WriteString(err.Error())
}
return s.String()
}
func (mu Multi) Clean() Multi {
out := make(Multi, 0, len(mu))
for _, err := range mu {
if err != nil {
out = append(out, err)
}
}
return out
}
func (mu Multi) Resolve() error {
out := mu.Clean()
if len(out) == 0 {
return nil
}
return out
}
// Close closes multiple close functions in go routines
// and returns all that errors in the order they are defined.
//
// All errors that are nil will be discarded from the list.
//
// If no errors met, Close returns nil.
func Close(funcs ...func() error) error {
if len(funcs) == 0 {
return nil
}
errs := make(Multi, len(funcs))
wg := sync.WaitGroup{}
wg.Add(len(funcs))
for i, fn := range funcs {
go func(i int, fn func() error) {
defer wg.Done()
errs[i] = fn()
}(i, fn)
}
wg.Wait()
return errs.Resolve()
}
// Join joins the error into one error.
//
// Join discards errors that are nil.
//
// If all errs are nil, Join returns nil.
func Join(errs ...error) error {
if len(errs) == 0 {
return nil
}
return Multi(errs).Resolve()
}