def create_joining_subplan(<EOL>pipeline_def, solid, join_step_key, parallel_steps, parallel_step_output<EOL>):
check.inst_param(pipeline_def, '<STR_LIT>', PipelineDefinition)<EOL>check.inst_param(solid, '<STR_LIT>', Solid)<EOL>check.str_param(join_step_key, '<STR_LIT>')<EOL>check.list_param(parallel_steps, '<STR_LIT>', of_type=ExecutionStep)<EOL>check.str_param(parallel_step_output, '<STR_LIT>')<EOL>for parallel_step in parallel_steps:<EOL><INDENT>check.invariant(parallel_step.has_step_output(parallel_step_output))<EOL><DEDENT>join_step = create_join_step(<EOL>pipeline_def, solid, join_step_key, parallel_steps, parallel_step_output<EOL>)<EOL>output_name = join_step.step_outputs[<NUM_LIT:0>].name<EOL>return ExecutionValueSubplan(<EOL>parallel_steps + [join_step], StepOutputHandle.from_step(join_step, output_name)<EOL>)<EOL>
This captures a common pattern of fanning out a single value to N steps,
where each step has similar structure. The strict requirement here is that each step
must provide an output named the parameters parallel_step_output.

This takes those steps and then uses a join node to coalesce them so that downstream
steps can depend on a single output.

Currently the join step just does a passthrough with no computation. It remains
to be seen if there should be any work or verification done in this step, especially
in multi-process environments that require persistence between steps.