package app import ( "context" "errors" "fmt" ) type Runner struct { Name string Run func(context.Context) error } type runnerResult struct { name string err error } func RunConcurrent(ctx context.Context, runners ...Runner) error { if len(runners) == 0 { return nil } ctx, cancel := context.WithCancel(ctx) defer cancel() results := make(chan runnerResult, len(runners)) for _, runner := range runners { runner := runner go func() { results <- runnerResult{name: runner.Name, err: runner.Run(ctx)} }() } var resultErr error for range runners { result := <-results if result.err != nil { resultErr = errors.Join(resultErr, fmt.Errorf("%s flow: %w", result.name, result.err)) cancel() } } return resultErr }