Last active
August 5, 2023 21:34
-
-
Save yael-castro/9b6586ced811305df051692fd30ff61a to your computer and use it in GitHub Desktop.
Stop n goroutines in case of any failure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package main | |
// | |
// - This is an example of how to stop several concurrent processes if an unexpected error occurs in one process. | |
// - This is a specific example of error management in multiple processes that can serve as a basis for solving other similar problems. | |
// | |
// Go Playground: https://go.dev/play/p/FrDs5m4fzWZ | |
// | |
package main | |
import ( | |
"context" | |
"errors" | |
"math/rand" | |
"strconv" | |
"sync" | |
"time" | |
) | |
// timeout random timeout for the process function | |
var timeout = time.Duration(rand.Intn(1_500)) * time.Millisecond | |
// process simulates some process that will run concurrently | |
func process(ctx context.Context, index int) error { | |
select { | |
case <-ctx.Done(): | |
return ctx.Err() | |
case <-time.After(time.Second): // Simulates process execution time | |
return nil | |
case <-time.After(timeout): // Simulates process error | |
return errors.New("an unexpected error occurs during the process " + strconv.Itoa(index) + " after " + timeout.String()) | |
} | |
} | |
func main() { | |
ctx, cancel := context.WithCancel(context.TODO()) | |
defer cancel() // This line ensures that the context is cancelled and the resources associated with it are free. | |
wg := sync.WaitGroup{} | |
errCh := make(chan error, 1) // The channel must have at least one space to avoid a deadlock. | |
for index := 0; index < 1_000; index++ { | |
wg.Add(1) | |
go func(index int) { | |
defer wg.Done() | |
if err := process(ctx, index); err != nil { | |
select { | |
case <-ctx.Done(): | |
return | |
case errCh <- err: | |
cancel() | |
return | |
} | |
} | |
}(index) // Creating another index variable at each iteration avoids a data race condition. | |
} | |
wg.Wait() | |
close(errCh) // The channel must be closed to avoid a deadlock. | |
// Error management | |
if err := <-errCh; err != nil { | |
println("Error:", err.Error()) | |
return | |
} | |
println("Done!") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment