private <O> PipelineBuilder<I, O> thenProcessInParallel(
      final String stageName,
      final Supplier<Processor<T, O>> createProcessor,
      final int numberOfThreads,
      final int newBufferSize) {
    final Pipe<O> newPipeEnd = createPipe(newBufferSize, stageName, outputCounter);
    final WritePipe<O> outputPipe = new SharedWritePipe<>(newPipeEnd, numberOfThreads);
    final ArrayList<Stage> newStages = new ArrayList<>(stages);
    for (int i = 0; i < numberOfThreads; i++) {
      final Stage processStage =
          new ProcessingStage<>(stageName, pipeEnd, outputPipe, createProcessor.get());
      newStages.add(processStage);
    }
    return new PipelineBuilder<>(
        inputPipe,
        newStages,
        concat(pipes, newPipeEnd),
        stageName,
        newPipeEnd,
        newBufferSize,
        outputCounter,
        tracingEnabled,
        pipelineName);
  }
End the pipeline with a {@link Consumer} that is the last stage of the pipeline.

@param stageName the name of this stage. Used as the label for the output count metric.
@param completer the {@link Consumer} that accepts the final output of the pipeline.
@return the constructed pipeline ready to execute.
services/pipeline/src/main/java/org/hyperledger/besu/services/pipeline/PipelineBuilder.java