mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 02:16:28 +02:00
54 lines
1.1 KiB
Go
54 lines
1.1 KiB
Go
// Package errgrouputil contains methods for working with errgroup code.
|
|
package errgrouputil
|
|
|
|
import (
|
|
"context"
|
|
"runtime"
|
|
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
"github.com/pomerium/pomerium/pkg/slices"
|
|
)
|
|
|
|
// BuilderFunc is a function that builds a value of type T
|
|
type BuilderFunc[T any] func(ctx context.Context) (*T, error)
|
|
|
|
// Build builds a slice of values of type T using the provided builders concurrently
|
|
// and returns the results and any errors.
|
|
func Build[T any](
|
|
ctx context.Context,
|
|
builders ...BuilderFunc[T],
|
|
) ([]*T, []error) {
|
|
eg, ctx := errgroup.WithContext(ctx)
|
|
eg.SetLimit(runtime.GOMAXPROCS(0)/2 + 1)
|
|
|
|
results := make([]*T, len(builders))
|
|
errors := make([]error, len(builders))
|
|
|
|
fn := func(i int) func() error {
|
|
return func() error {
|
|
result, err := builders[i](ctx)
|
|
if err != nil {
|
|
errors[i] = err
|
|
return nil
|
|
}
|
|
results[i] = result
|
|
return nil
|
|
}
|
|
}
|
|
|
|
for i := range builders {
|
|
eg.Go(fn(i))
|
|
}
|
|
|
|
err := eg.Wait()
|
|
if err != nil {
|
|
return nil, []error{err} // not happening
|
|
}
|
|
|
|
return slices.Filter(results, func(t *T) bool {
|
|
return t != nil
|
|
}), slices.Filter(errors, func(err error) bool {
|
|
return err != nil
|
|
})
|
|
}
|