Wait waits for each stage in the pipeline to exit.
()
| 179 | |
| 180 | // Wait waits for each stage in the pipeline to exit. |
| 181 | func (p *Pipeline) Wait() error { |
| 182 | if !p.hasStarted() { |
| 183 | panic("unable to wait on a pipeline that has not started") |
| 184 | } |
| 185 | |
| 186 | // Make sure that all of the cleanup eventually happens: |
| 187 | defer p.cancel() |
| 188 | |
| 189 | var earliestStageErr error |
| 190 | var earliestFailedStage Stage |
| 191 | |
| 192 | finishedEarly := false |
| 193 | for i := len(p.stages) - 1; i >= 0; i-- { |
| 194 | s := p.stages[i] |
| 195 | err := s.Wait() |
| 196 | |
| 197 | // Handle errors: |
| 198 | switch { |
| 199 | case err == nil: |
| 200 | // No error to handle. But unset the `finishedEarly` flag, |
| 201 | // because earlier stages shouldn't be affected by the |
| 202 | // later stage that finished early. |
| 203 | finishedEarly = false |
| 204 | continue |
| 205 | |
| 206 | case errors.Is(err, FinishEarly): |
| 207 | // We ignore `FinishEarly` errors because that is how a |
| 208 | // stage informs us that it intentionally finished early. |
| 209 | // Moreover, if we see a `FinishEarly` error, ignore any |
| 210 | // pipe error from the immediately preceding stage, |
| 211 | // because it probably came from trying to write to this |
| 212 | // stage after this stage closed its stdin. |
| 213 | finishedEarly = true |
| 214 | continue |
| 215 | |
| 216 | case IsPipeError(err): |
| 217 | switch { |
| 218 | case finishedEarly: |
| 219 | // A successor stage finished early. It is common for |
| 220 | // this to cause earlier stages to fail with pipe |
| 221 | // errors. Such errors are uninteresting, so ignore |
| 222 | // them. Leave the `finishedEarly` flag set, because |
| 223 | // the preceding stage might get a pipe error from |
| 224 | // trying to write to this one. |
| 225 | case earliestStageErr != nil: |
| 226 | // A later stage has already reported an error. This |
| 227 | // means that we don't want to report the error from |
| 228 | // this stage: |
| 229 | // |
| 230 | // * If the later error was also a pipe error: we want |
| 231 | // to report the _last_ pipe error seen, which would |
| 232 | // be the one already recorded. |
| 233 | // |
| 234 | // * If the later error was not a pipe error: non-pipe |
| 235 | // errors are always considered more important than |
| 236 | // pipe errors, so again we would want to keep the |
| 237 | // error that is already recorded. |
| 238 | default: |
no test coverage detected