use crate::pipeline::PipelineFile;
use super::closing::ChainFailure;
use super::node_outputs::NodeRecords;
use super::{ChainPosition, NodeExecutionResult, PipelineContext, PipelineNodeRef, execute_node};
pub(super) fn run_node_chain<F: Fn() -> u64 + Copy>(
ctx: &PipelineContext<F>,
nodes: &[PipelineNodeRef],
files: Vec<PipelineFile>,
file_offset: usize,
position: ChainPosition,
) -> Result<NodeExecutionResult, ChainFailure> {
let mut chain_ctx = ctx.layer();
let mut chain = NodeExecutionResult::holding(files);
let total = position.total_nodes;
for (i, node) in nodes.iter().enumerate() {
let files = std::mem::take(&mut chain.output_files);
let index = position.first_index + i;
match execute_node(&chain_ctx, node, files, index, total, file_offset) {
Ok(result) => {
let records = chain.then(result);
chain_ctx.node_outputs.add(records, ctx.count_keys);
}
Err(error) => {
let failure = ChainFailure::new(&node.id, error);
let rest = &nodes[i + 1..];
return Err(failure.close(&mut chain_ctx, rest, file_offset, position.after(i)));
}
}
}
chain.node_outputs = chain_ctx.node_outputs.into_own();
Ok(chain)
}
impl NodeExecutionResult {
pub(super) fn holding(files: Vec<PipelineFile>) -> Self {
Self {
output_files: files,
files_processed: 0,
warnings: Vec::new(),
node_outputs: NodeRecords::new(),
}
}
pub(super) fn then(&mut self, next: NodeExecutionResult) -> NodeRecords {
self.output_files = next.output_files;
self.files_processed += next.files_processed;
self.warnings.extend(next.warnings);
next.node_outputs
}
}