use hyperdb_api::grpc::{GrpcConfig, GrpcConnection, GrpcConnectionAsync};
use hyperdb_api::{HyperProcess, ListenMode, Parameters, Result};
fn grpc_hyperd() -> Result<(HyperProcess, String)> {
let mut params = Parameters::new();
params.set("log_dir", "test_results");
params.set_listen_mode(ListenMode::Grpc { port: 0 });
let hyper = HyperProcess::new(None, Some(¶ms))?;
let url = hyper
.grpc_url()
.expect("hyperd should expose a gRPC URL when listen_mode=Grpc");
Ok((hyper, url))
}
#[test]
fn cancel_query_sync_does_not_poison_the_channel() -> Result<()> {
let (hyper, url) = grpc_hyperd()?;
let config = GrpcConfig::new(&url);
let mut conn = GrpcConnection::connect_with_config(config)?;
let cancel_result = conn.cancel_query("test-synthetic-query-id");
match &cancel_result {
Ok(()) => {}
Err(e) => eprintln!("cancel_query returned error (acceptable): {e}"),
}
let arrow = conn.execute_query_to_arrow("SELECT 1")?;
assert!(
!arrow.is_empty(),
"follow-up query after cancel returned empty arrow data",
);
drop(conn);
drop(hyper);
Ok(())
}
#[test]
fn cancel_query_async_does_not_poison_the_channel() -> Result<()> {
let (hyper, url) = grpc_hyperd()?;
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("failed to build tokio runtime");
runtime.block_on(async {
let config = GrpcConfig::new(&url);
let mut conn = GrpcConnectionAsync::connect_with_config(config).await?;
let cancel_result = conn.cancel_query("test-synthetic-query-id").await;
match &cancel_result {
Ok(()) => {}
Err(e) => eprintln!("cancel_query returned error (acceptable): {e}"),
}
let arrow = conn.execute_query_to_arrow("SELECT 1").await?;
assert!(
!arrow.is_empty(),
"follow-up query after cancel returned empty arrow data",
);
Result::Ok(())
})?;
drop(hyper);
Ok(())
}
#[test]
fn cancel_query_with_real_query_id_succeeds_or_errors_cleanly() -> Result<()> {
let (hyper, url) = grpc_hyperd()?;
let config = GrpcConfig::new(&url);
let mut conn = GrpcConnection::connect_with_config(config)?;
let result = conn.execute_query("SELECT 1 AS one")?;
if let Some(query_id) = result.query_id() {
match conn.cancel_query(query_id) {
Ok(()) => {}
Err(e) => eprintln!(
"cancel_query on completed query returned {e} \
(acceptable: server may reject cancel of finished query)",
),
}
} else {
let _ = conn.cancel_query("no-such-query-id");
}
let arrow = conn.execute_query_to_arrow("SELECT 2")?;
assert!(!arrow.is_empty());
drop(conn);
drop(hyper);
Ok(())
}