Skip to content

Support nested Pipeline in prologue and epilogue #31

@julio4

Description

@julio4

Currently Pipeline's prologue/epilogue take a single Step:

let pipeline = Pipeline::<Ethereum>::default()
	.with_epilogue(BuilderEpilogue)
	.with_pipeline(
		Loop,
		(
			AppendOneOrder::default(),
			PriorityFeeOrdering,
			TotalProfitOrdering,
			RevertProtection,
		),
	)
	.with_prologue(BuilderPrologue);

In some cases, it can be useful to be able to execute mutliple steps in prologue/epilogue. I.e.:

let pipeline = Pipeline::<Ethereum>::default()
	.with_epilogue(Once, (BuilderEpilogue, CustomEpilogueStep))
	.with_pipeline(
		Loop,
		(
			AppendOneOrder::default(),
			PriorityFeeOrdering,
			TotalProfitOrdering,
			RevertProtection,
		),
	)
	.with_prologue(Once, (BuilderPrologue, CustomPrologueStep));

Implementation

Similarly to steps in pipeline, we could use StepOrPipeline instead of single Step instance:

epilogue: Option<Arc<StepInstance<P>>>,
prologue: Option<Arc<StepInstance<P>>>,

This is not a small change, as it modify how pipelines are executed, and need some changes around Pipeline navigation:

  • Update pipelines::exec::navi to correctly explore nested pipelines
  • Similarly, also update StepPathIter
    // Yield prologue once, if present.
    if !frame.yielded_prologue && frame.pipeline.prologue.is_some() {
    frame.yielded_prologue = true;
    return Some(frame.path.clone().concat(StepPath::prologue()));
    }
    // Walk steps; descend into nested pipelines.
    if frame.next_ix < frame.pipeline.steps.len() {
    let ix = frame.next_ix;
    frame.next_ix += 1;
    match &frame.pipeline.steps[ix] {
    StepOrPipeline::Step(_) => {
    return Some(frame.path.clone().concat(StepPath::step(ix)));
    }
    StepOrPipeline::Pipeline(_, nested) => {
    let next_path = frame.path.clone().concat(StepPath::step(ix));
    self.stack.push(Frame {
    pipeline: nested,
    path: next_path,
    next_ix: 0,
    yielded_prologue: false,
    yielded_epilogue: false,
    });
    continue;
    }
    }
    }
    // Yield epilogue once, if present.
    if !frame.yielded_epilogue && frame.pipeline.epilogue.is_some() {
    frame.yielded_epilogue = true;
    return Some(frame.path.clone().concat(StepPath::epilogue()));
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions