feat: Start converting method calls to async

This commit is contained in:
Stephen Christie
2023-08-27 17:11:20 -04:00
parent b9603dc0a1
commit 5634729445
4 changed files with 70 additions and 193 deletions

View File

@@ -1,5 +1,6 @@
use crate::nodes::Node;
use crate::{core::client::Client, nodes::Message};
use async_trait::async_trait;
use color_eyre::eyre::Result;
use once_cell::sync::OnceCell;
use stardust_xr::scenegraph;
@@ -50,6 +51,7 @@ impl Scenegraph {
}
}
#[async_trait]
impl scenegraph::Scenegraph for Scenegraph {
fn send_signal(
&self,
@@ -58,7 +60,9 @@ impl scenegraph::Scenegraph for Scenegraph {
data: &[u8],
fds: Vec<OwnedFd>,
) -> Result<(), ScenegraphError> {
let Some(client) = self.get_client() else {return Err(ScenegraphError::SignalNotFound)};
let Some(client) = self.get_client() else {
return Err(ScenegraphError::SignalNotFound);
};
debug_span!("Handle signal", path, method).in_scope(|| {
self.get_node(path)
.ok_or(ScenegraphError::NodeNotFound)?
@@ -72,27 +76,29 @@ impl scenegraph::Scenegraph for Scenegraph {
)
})
}
fn execute_method(
async fn execute_method(
&self,
path: &str,
method: &str,
data: &[u8],
fds: Vec<OwnedFd>,
) -> Result<(Vec<u8>, Vec<OwnedFd>), ScenegraphError> {
let Some(client) = self.get_client() else {return Err(ScenegraphError::MethodNotFound)};
debug_span!("Handle method", path, method).in_scope(|| {
let message = self
.get_node(path)
.ok_or(ScenegraphError::NodeNotFound)?
.execute_local_method(
client,
method,
Message {
data: data.to_vec(),
fds,
},
)?;
Ok((message.data, message.fds))
})
let Some(client) = self.get_client() else {
return Err(ScenegraphError::MethodNotFound);
};
debug!(path, method, "Handle method");
let message = self
.get_node(path)
.ok_or(ScenegraphError::NodeNotFound)?
.execute_local_method(
client,
method,
Message {
data: data.to_vec(),
fds,
},
)
.await?;
Ok((message.data, message.fds))
}
}

View File

@@ -10,6 +10,7 @@ pub mod root;
pub mod spatial;
pub mod startup;
use async_recursion::async_recursion;
use color_eyre::eyre::{eyre, Result};
use core::hash::BuildHasherDefault;
use dashmap::DashMap;
@@ -22,7 +23,9 @@ use stardust_xr::messenger::MessageSenderHandle;
use stardust_xr::scenegraph::ScenegraphError;
use stardust_xr::schemas::flex::deserialize;
use std::fmt::Debug;
use std::future::Future;
use std::os::fd::OwnedFd;
use std::pin::Pin;
use std::sync::{Arc, Weak};
use std::vec::Vec;
use tracing::{debug_span, instrument};
@@ -60,7 +63,11 @@ impl AsRef<[u8]> for Message {
}
pub type Signal = fn(&Node, Arc<Client>, Message) -> Result<()>;
pub type Method = fn(&Node, Arc<Client>, Message) -> Result<Message>;
pub type Method = fn(
&Node,
Arc<Client>,
Message,
) -> Pin<Box<dyn Future<Output = Result<Message>> + Send + Sync + 'static>>;
pub struct Node {
pub enabled: Arc<AtomicBool>,
@@ -186,8 +193,15 @@ impl Node {
pub fn add_local_signal(&self, name: &str, signal: Signal) {
self.local_signals.insert(name.to_string(), signal);
}
pub fn add_local_method(&self, name: &str, method: Method) {
self.local_methods.insert(name.to_string(), method);
pub fn add_local_method<F: Future<Output = Result<Message>> + Send + Sync + 'static>(
&self,
name: &str,
method: fn(&Node, Arc<Client>, Message) -> F,
) {
self.local_methods
.insert(name.to_string(), |node, calling_client, message| {
Box::Pin(method(node, calling_client, message))
});
}
pub fn get_aspect<F, T>(
@@ -229,7 +243,8 @@ impl Node {
})
}
}
pub fn execute_local_method(
#[async_recursion]
pub async fn execute_local_method(
&self,
calling_client: Arc<Client>,
method: &str,
@@ -251,19 +266,18 @@ impl Node {
fds: Vec::new(),
},
)
.await
} else {
let method = self
.local_methods
.get(method)
.ok_or(ScenegraphError::MethodNotFound)?;
debug_span!("Handle method").in_scope(|| {
method(self, calling_client, message).map_err(|error| {
ScenegraphError::MethodError {
error: error.to_string(),
}
method(self, calling_client, message)
.await
.map_err(|error| ScenegraphError::MethodError {
error: error.to_string(),
})
})
}
}
#[instrument(level = "debug", skip_all)]