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{index: index, err: integration.Run(ctx)}
42 for remaining := len(drivers); remaining > 0; {
44 case _, open := <-connected:
51 for _, integration := range drivers {
54 case result := <-results:
56 if result.err == nil || ctx.Err() != nil && stopOnly(result.err, ctx.Err()) {
60 slog.Error("driver failed", "driver", result.index, "err", result.err)
62 failures = append(failures, fmt.Errorf("run driver %d: %w", result.index, result.err))
68 return errors.Join(failures...)
71 type driverResult struct {
76 func stopOnly(err error, cancellation error) bool {
77 joined, ok := err.(interface{ Unwrap() []error })
81 for _, cause := range joined.Unwrap() {
84 if !stopOnly(cause, cancellation) {
93 wrapped, ok := err.(interface{ Unwrap() error })
95 return stopOnly(wrapped.Unwrap(), cancellation)
98 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)