blob: 772f90b1e46ca67356b7d014b810e9927144aaab [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use std::{future::Future, time::Duration};
use pyo3::Python;
use tokio::{runtime::Runtime, time::sleep};
use crate::error::PySedonaError;
// Adapted from datafusion-python:
// https://github.com/apache/datafusion-python/blob/7aff3635c93d5897d470642928c39c86e7851931/src/utils.rs#L80-L106
pub fn wait_for_future<F>(py: Python, runtime: &Runtime, fut: F) -> Result<F::Output, PySedonaError>
where
F: Future + Send,
F::Output: Send,
{
const INTERVAL_CHECK_SIGNALS: Duration = Duration::from_millis(2_000);
py.run(cr"pass", None, None)?;
py.check_signals()?;
py.allow_threads(|| {
runtime.block_on(async {
tokio::pin!(fut);
loop {
tokio::select! {
res = &mut fut => break Ok(res),
_ = sleep(INTERVAL_CHECK_SIGNALS) => {
Python::with_gil(|py| {
py.run(cr"pass", None, None)?;
py.check_signals()
})?;
}
}
}
})
})
}
// A version of the above except for use from an arbitrary Rust function instead
// of from somewhere that had already acquired the GIL.
pub fn wait_for_future_from_rust<F>(runtime: &Runtime, fut: F) -> Result<F::Output, PySedonaError>
where
F: Future + Send,
F::Output: Send,
{
const INTERVAL_CHECK_SIGNALS: Duration = Duration::from_millis(2_000);
runtime.block_on(async {
tokio::pin!(fut);
loop {
tokio::select! {
res = &mut fut => break Ok(res),
_ = sleep(INTERVAL_CHECK_SIGNALS) => {
Python::with_gil(|py| {
py.run(cr"pass", None, None)?;
py.check_signals()
})?;
}
}
}
})
}