A test that mocks the behavior of `SpillManager::read_spill_as_stream` without file access to verify that a cooperative stream would properly yields in a spill file read scenario
()
| 272 | // A test that mocks the behavior of `SpillManager::read_spill_as_stream` without file access |
| 273 | // to verify that a cooperative stream would properly yields in a spill file read scenario |
| 274 | async fn spill_reader_stream_yield() -> Result<(), Box<dyn Error>> { |
| 275 | use datafusion_physical_plan::common::spawn_buffered; |
| 276 | |
| 277 | // A mock stream that always returns `Poll::Ready(Some(...))` immediately |
| 278 | let always_ready = |
| 279 | make_lazy_exec("value", false).execute(0, SessionContext::new().task_ctx())?; |
| 280 | |
| 281 | // this function makes a consumer stream that resembles how read_stream from spill file is constructed |
| 282 | let stream = make_cooperative(always_ready); |
| 283 | |
| 284 | // Set large buffer so that buffer always has free space for the producer/sender |
| 285 | let buffer_capacity = 100_000; |
| 286 | let mut mock_stream = spawn_buffered(stream, buffer_capacity); |
| 287 | let schema = mock_stream.schema(); |
| 288 | |
| 289 | let consumer_stream = futures::stream::poll_fn(move |cx| { |
| 290 | let mut collected = vec![]; |
| 291 | // To make sure that inner stream is polled multiple times, loop until the buffer is full |
| 292 | // Ideally, the stream will yield before the loop ends |
| 293 | for _ in 0..buffer_capacity { |
| 294 | match mock_stream.as_mut().poll_next(cx) { |
| 295 | Poll::Ready(Some(Ok(batch))) => { |
| 296 | collected.push(batch); |
| 297 | } |
| 298 | Poll::Ready(Some(Err(e))) => { |
| 299 | return Poll::Ready(Some(Err(e))); |
| 300 | } |
| 301 | Poll::Ready(None) => { |
| 302 | break; |
| 303 | } |
| 304 | Poll::Pending => { |
| 305 | // polling inner stream may return Pending only when it reaches budget, since |
| 306 | // we intentionally made ProducerStream always return Ready |
| 307 | return Poll::Pending; |
| 308 | } |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | // This should be unreachable since the stream is canceled |
| 313 | unreachable!("Expected the stream to be canceled, but it continued polling"); |
| 314 | }); |
| 315 | |
| 316 | let consumer_record_batch_stream = |
| 317 | Box::pin(RecordBatchStreamAdapter::new(schema, consumer_stream)); |
| 318 | |
| 319 | stream_yields(consumer_record_batch_stream).await |
| 320 | } |
| 321 | |
| 322 | #[rstest] |
| 323 | #[tokio::test] |
nothing calls this directly
no test coverage detected
searching dependent graphs…