Fix gRPC stream panic: use async stream combinators instead of block_on

The gRPC streaming code was using tokio::runtime::Handle::current().block_on()
inside filter_map closures, which caused a panic ('Cannot start a runtime from
within a runtime') when called from an async context.

Fixed by replacing the pattern with .then(async move { ... }).filter_map(|x| x)
which properly handles async operations in stream pipelines.

This fixes the gRPC Ping/Pong freeze issue and restores request cancellation.
This commit is contained in:
Gregory Schier
2026-01-10 14:31:39 -08:00
parent fe01796536
commit aa79fb05f9
2 changed files with 49 additions and 45 deletions

View File

@@ -392,7 +392,7 @@ async fn cmd_grpc_go<R: Runtime>(
let encryption_manager = encryption_manager.clone(); let encryption_manager = encryption_manager.clone();
let msg = block_in_place(|| { let msg = block_in_place(|| {
tauri::async_runtime::block_on(async { tauri::async_runtime::block_on(async {
render_template( let result = render_template(
msg.as_str(), msg.as_str(),
environment_chain, environment_chain,
&PluginTemplateCallback::new( &PluginTemplateCallback::new(
@@ -406,8 +406,8 @@ async fn cmd_grpc_go<R: Runtime>(
), ),
&RenderOptions { error_behavior: RenderErrorBehavior::Throw }, &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
) )
.await .await;
.expect("Failed to render template") result.expect("Failed to render template")
}) })
}); });
in_msg_tx.try_send(msg.clone()).unwrap(); in_msg_tx.try_send(msg.clone()).unwrap();

View File

@@ -131,31 +131,33 @@ impl GrpcConnection {
let md = metadata.clone(); let md = metadata.clone();
let use_reflection = self.use_reflection.clone(); let use_reflection = self.use_reflection.clone();
let client_cert = client_cert.clone(); let client_cert = client_cert.clone();
stream.filter_map(move |json| { stream
let pool = pool.clone(); .then(move |json| {
let uri = uri.clone(); let pool = pool.clone();
let input_message = input_message.clone(); let uri = uri.clone();
let md = md.clone(); let input_message = input_message.clone();
let use_reflection = use_reflection.clone(); let md = md.clone();
let client_cert = client_cert.clone(); let use_reflection = use_reflection.clone();
tokio::runtime::Handle::current().block_on(async move { let client_cert = client_cert.clone();
if use_reflection { async move {
if let Err(e) = if use_reflection {
reflect_types_for_message(pool, &uri, &json, &md, client_cert).await if let Err(e) =
{ reflect_types_for_message(pool, &uri, &json, &md, client_cert).await
warn!("Failed to resolve Any types: {e}"); {
warn!("Failed to resolve Any types: {e}");
}
} }
} let mut de = Deserializer::from_str(&json);
let mut de = Deserializer::from_str(&json); match DynamicMessage::deserialize(input_message, &mut de) {
match DynamicMessage::deserialize(input_message, &mut de) { Ok(m) => Some(m),
Ok(m) => Some(m), Err(e) => {
Err(e) => { warn!("Failed to deserialize message: {e}");
warn!("Failed to deserialize message: {e}"); None
None }
} }
} }
}) })
}) .filter_map(|x| x)
}; };
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone()); let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());
@@ -185,31 +187,33 @@ impl GrpcConnection {
let md = metadata.clone(); let md = metadata.clone();
let use_reflection = self.use_reflection.clone(); let use_reflection = self.use_reflection.clone();
let client_cert = client_cert.clone(); let client_cert = client_cert.clone();
stream.filter_map(move |json| { stream
let pool = pool.clone(); .then(move |json| {
let uri = uri.clone(); let pool = pool.clone();
let input_message = input_message.clone(); let uri = uri.clone();
let md = md.clone(); let input_message = input_message.clone();
let use_reflection = use_reflection.clone(); let md = md.clone();
let client_cert = client_cert.clone(); let use_reflection = use_reflection.clone();
tokio::runtime::Handle::current().block_on(async move { let client_cert = client_cert.clone();
if use_reflection { async move {
if let Err(e) = if use_reflection {
reflect_types_for_message(pool, &uri, &json, &md, client_cert).await if let Err(e) =
{ reflect_types_for_message(pool, &uri, &json, &md, client_cert).await
warn!("Failed to resolve Any types: {e}"); {
warn!("Failed to resolve Any types: {e}");
}
} }
} let mut de = Deserializer::from_str(&json);
let mut de = Deserializer::from_str(&json); match DynamicMessage::deserialize(input_message, &mut de) {
match DynamicMessage::deserialize(input_message, &mut de) { Ok(m) => Some(m),
Ok(m) => Some(m), Err(e) => {
Err(e) => { warn!("Failed to deserialize message: {e}");
warn!("Failed to deserialize message: {e}"); None
None }
} }
} }
}) })
}) .filter_map(|x| x)
}; };
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone()); let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());