|
17 | 17 |
|
18 | 18 | use crate::{ |
19 | 19 | common::data_type::PyScalarValue, |
20 | | - errors::{PyDataFusionError, PyDataFusionResult}, |
| 20 | + errors::{to_datafusion_err, PyDataFusionError, PyDataFusionResult}, |
21 | 21 | TokioRuntime, |
22 | 22 | }; |
23 | 23 | use datafusion::{ |
24 | | - common::ScalarValue, execution::context::SessionContext, logical_expr::Volatility, |
| 24 | + common::ScalarValue, execution::context::SessionContext, execution::SendableRecordBatchStream, |
| 25 | + logical_expr::Volatility, |
25 | 26 | }; |
26 | 27 | use pyo3::prelude::*; |
27 | 28 | use pyo3::{exceptions::PyValueError, types::PyCapsule}; |
28 | 29 | use std::{future::Future, sync::OnceLock, time::Duration}; |
29 | | -use tokio::{runtime::Runtime, time::sleep}; |
| 30 | +use tokio::{runtime::Runtime, task::JoinHandle, time::sleep}; |
30 | 31 | /// Utility to get the Tokio Runtime from Python |
31 | 32 | #[inline] |
32 | 33 | pub(crate) fn get_tokio_runtime() -> &'static TokioRuntime { |
|
84 | 85 | }) |
85 | 86 | } |
86 | 87 |
|
| 88 | +/// Spawn a [`SendableRecordBatchStream`] on the Tokio runtime and wait for completion |
| 89 | +/// while respecting Python signal handling. |
| 90 | +pub(crate) fn spawn_stream<F>(py: Python, fut: F) -> PyDataFusionResult<SendableRecordBatchStream> |
| 91 | +where |
| 92 | + F: Future<Output = datafusion::common::Result<SendableRecordBatchStream>> + Send + 'static, |
| 93 | +{ |
| 94 | + let rt = &get_tokio_runtime().0; |
| 95 | + let handle: JoinHandle<datafusion::common::Result<SendableRecordBatchStream>> = rt.spawn(fut); |
| 96 | + wait_for_future(py, async { handle.await.map_err(to_datafusion_err) })??? |
| 97 | +} |
| 98 | + |
87 | 99 | pub(crate) fn parse_volatility(value: &str) -> PyDataFusionResult<Volatility> { |
88 | 100 | Ok(match value { |
89 | 101 | "immutable" => Volatility::Immutable, |
|
0 commit comments