14 // Run starts the explicit driver list and waits for every driver to stop. A
15 // failure cancels the other drivers. Reconnect notifications request fresh
16 // snapshots. A nil or closed connected channel disables notifications. An empty
17 // list waits for cancellation. Only this runner logs driver failures.
18 func Run(ctx context.Context, drivers []Driver, connected <-chan struct{}) error {
19 ctx, cancel := context.WithCancel(ctx)
22 if len(drivers) == 0 {
28 results := make(chan driverResult, len(drivers))
30 var workers sync.WaitGroup
32 for index, integration := range drivers {
34 results <- driverResult{
36 err: integration.Run(ctx),
45 for remaining := len(drivers); remaining > 0; {
47 case _, open := <-connected:
54 for _, integration := range drivers {
57 case result := <-results:
59 if result.err == nil || ctx.Err() != nil && stopOnly(result.err, ctx.Err()) {
63 slog.Error("driver failed", "driver", result.index, "err", result.err)
65 failures = append(failures, fmt.Errorf("run driver %d: %w", result.index, result.err))
71 return errors.Join(failures...)
74 func stopOnly(err error, cancellation error) bool {
75 joined, ok := err.(interface{ Unwrap() []error })
79 for _, cause := range joined.Unwrap() {
82 if !stopOnly(cause, cancellation) {
91 wrapped, ok := err.(interface{ Unwrap() error })
93 return stopOnly(wrapped.Unwrap(), cancellation)
96 return errors.Is(err, cancellation) || errors.Is(err, net.ErrClosed) || errors.Is(err, io.ErrClosedPipe) || errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET)