Describe the bug
Given a RepartitionExec where its input stream does not have a record batch for immediate consumption, it will terminate early.
I found this while trying to figure out why this plan was failing in IOx (nothing ever bothered to read from the stream provided to RepartionExec:
ProjectionExec: expr=[town, count]
RepartitionExec: partitioning=RoundRobinBatch(16)
IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate
To Reproduce
Set up a plan like this:
┌───────────────────┐ ┌───────────────────────┐
│ │ │ │
│ InputStream │───────▶│ RepartitionStream │
│ │ │ │
└───────────────────┘ └───────────────────────┘
Where the input stream won't produce the record batch immediately. Full reproducer below.
I expect to the repartition stream to produce the same record batch as the input stream (will) provide (or produce a meaningful error). However, I get nothing!
expected:
[
"+------------------+",
"| my_awesome_field |",
"+------------------+",
"| foo |",
"| bar |",
"+------------------+",
]
actual:
[
"++",
"++",
]
Full Reproducer (run in repartition.rs)
Add any other context about the problem here.
#[tokio::test]asyncfnrepartition_with_delayed_stream(){let input = DelayedExec::new();let partitioning = input.output_partitioning();let expected_batches = vec![input.batch.clone()];let exec = RepartitionExec::try_new(Arc::new(input), partitioning).unwrap();let expected = vec!["+------------------+","| my_awesome_field |","+------------------+","| foo |","| bar |","+------------------+",];assert_batches_eq!(&expected,&expected_batches);let output_stream = exec.execute(0).await.unwrap();let batches = crate::physical_plan::common::collect(output_stream).await.unwrap();assert_batches_eq!(&expected,&batches);}#[derive(Debug)]structDelayedExec{batch:RecordBatch}implDelayedExec{fnnew() -> Self{let batch = RecordBatch::try_from_iter(vec![("my_awesome_field",Arc::new(StringArray::from(vec!["foo","bar"]))asArrayRef)]).unwrap();Self{
batch
}}}#[async_trait]implExecutionPlanforDelayedExec{fnas_any(&self) -> &dynAny{self}fnschema(&self) -> SchemaRef{self.batch.schema()}fnoutput_partitioning(&self) -> Partitioning{Partitioning::UnknownPartitioning(1)}fnchildren(&self) -> Vec<Arc<dynExecutionPlan>>{unimplemented!()}fnwith_new_children(&self,_children:Vec<Arc<dynExecutionPlan>>,) -> Result<Arc<dynExecutionPlan>>{unimplemented!()}/// Returns a stream which does not have data immediately, but/// needs to yield (to allow another task to run) to get its/// input.asyncfnexecute(&self,partition:usize) -> Result<SendableRecordBatchStream>{assert_eq!(partition,0);let batch = self.batch.clone();let schema = batch.schema();let(tx, rx) = tokio::sync::mpsc::channel(2);// task simply sends the batch
tokio::task::spawn(asyncmove{println!("Sending batch via delayed stream");ifletErr(e) = tx.send(Ok(batch.clone())).await{println!("ERROR batch via delayed stream: {}", e);}});// returned stream simply reads off the rx streamlet stream = ParquetStream{
schema,inner:ReceiverStream::new(rx),};Ok(Box::pin(stream))}}#[derive(Debug)]pubstructParquetStream{schema:SchemaRef,inner:ReceiverStream<ArrowResult<RecordBatch>>,}implStreamforParquetStream{typeItem = ArrowResult<RecordBatch>;fnpoll_next(mutself: std::pin::Pin<&mutSelf>,cx:&mutContext<'_>,) -> Poll<Option<Self::Item>>{println!("ParquetStream::poll_next");let res = self.inner.poll_next_unpin(cx);println!("ParquetStream::poll_next() done");
res
}}implRecordBatchStreamforParquetStream{fnschema(&self) -> SchemaRef{Arc::clone(&self.schema)}}implDropforParquetStream{fndrop(&mutself){println!("ParquetStream::drop()");}}
Describe the bug
Given a
RepartitionExecwhere its input stream does not have a record batch for immediate consumption, it will terminate early.I found this while trying to figure out why this plan was failing in IOx (nothing ever bothered to read from the stream provided to
RepartionExec:To Reproduce
Set up a plan like this:
Where the input stream won't produce the record batch immediately. Full reproducer below.
I expect to the repartition stream to produce the same record batch as the input stream (will) provide (or produce a meaningful error). However, I get nothing!
Full Reproducer (run in repartition.rs)
Add any other context about the problem here.