util: errwrap: Add unwrapping for context removal

It's common in many concurrent engines to have a situation where we
collect errors on shutdown. Errors can either because a context closed,
or because some engine error happened. The latter, can also cause the
former, leading to a list of returned errors. In these scenarios, we
want to filter out all the secondary context errors, unless that's all
that's there. This provides a helper function to do so.
This commit is contained in:
James Shubin
2025-07-16 23:46:09 -04:00
parent 299b49bb17
commit bdf5209f68
2 changed files with 181 additions and 0 deletions

View File

@@ -31,6 +31,8 @@
package errwrap
import (
"context"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
)
@@ -72,6 +74,42 @@ func Join(errs []error) error {
return reterr
}
// WithoutContext passes through an error if it's nil or is a normal error. If
// it is a multierror, then it removes all errors of context cancellation unless
// that's all there is. If there's one error remaining, it returns that.
// Otherwise it returns a new multierror with what's left.
func WithoutContext(err error) error {
if err == nil {
return nil
}
multiErr, ok := err.(*multierror.Error)
if !ok {
return err
}
if len(multiErr.Errors) == 0 {
return err // unexpected
}
errs := []error{}
for _, e := range multiErr.Errors {
if e == context.Canceled {
continue // remove
}
errs = append(errs, e)
}
if len(errs) == 0 {
return context.Canceled
}
//if len(errs) == 1 {
// return errs[0]
//}
return Join(errs)
}
// String returns a string representation of the error. In particular, if the
// error is nil, it returns an empty string instead of panicking.
func String(err error) string {