use std::future::Future;
use std::sync::Arc;
use crate::{
ContextPathNeighborhood, NeighborhoodRequest, NodeNeighborhood, NodeProjection, PortError,
};
pub trait GraphNeighborhoodReader {
fn load_nodes_batch(
&self,
node_ids: Vec<String>,
) -> impl Future<Output = Result<Vec<Option<NodeProjection>>, PortError>> + Send
where
Self: Sync,
{
async {
let mut nodes = Vec::with_capacity(node_ids.len());
for id in node_ids {
nodes.push(self.load_neighborhood(&id, 1).await?.map(|n| n.root));
}
Ok(nodes)
}
}
fn load_bounded_trace(
&self,
_request: &crate::TraceSearchRequest,
) -> impl Future<Output = Result<crate::TraceSearchResult, PortError>> + Send {
async {
Err(PortError::Unavailable(
"bounded trace search is not supported by this graph adapter".into(),
))
}
}
fn load_evidence_paths(
&self,
_request: &crate::EvidencePathRequest,
) -> impl Future<Output = Result<crate::EvidencePathResult, PortError>> + Send {
async {
Err(PortError::Unavailable(
"evidence paths are not supported by this graph adapter".into(),
))
}
}
fn load_neighborhood(
&self,
root_node_id: &str,
depth: u32,
) -> impl Future<Output = Result<Option<NodeNeighborhood>, PortError>> + Send;
fn load_scoped_neighborhood(
&self,
request: &NeighborhoodRequest,
) -> impl Future<Output = Result<Option<NodeNeighborhood>, PortError>> + Send {
self.load_neighborhood(request.root_node_id(), request.depth())
}
fn load_context_path(
&self,
root_node_id: &str,
target_node_id: &str,
subtree_depth: u32,
) -> impl Future<Output = Result<Option<ContextPathNeighborhood>, PortError>> + Send;
}
impl<T> GraphNeighborhoodReader for Arc<T>
where
T: GraphNeighborhoodReader + Send + Sync + ?Sized,
{
async fn load_nodes_batch(
&self,
node_ids: Vec<String>,
) -> Result<Vec<Option<NodeProjection>>, PortError> {
self.as_ref().load_nodes_batch(node_ids).await
}
async fn load_bounded_trace(
&self,
request: &crate::TraceSearchRequest,
) -> Result<crate::TraceSearchResult, PortError> {
self.as_ref().load_bounded_trace(request).await
}
async fn load_evidence_paths(
&self,
request: &crate::EvidencePathRequest,
) -> Result<crate::EvidencePathResult, PortError> {
self.as_ref().load_evidence_paths(request).await
}
async fn load_neighborhood(
&self,
root_node_id: &str,
depth: u32,
) -> Result<Option<NodeNeighborhood>, PortError> {
self.as_ref().load_neighborhood(root_node_id, depth).await
}
async fn load_scoped_neighborhood(
&self,
request: &NeighborhoodRequest,
) -> Result<Option<NodeNeighborhood>, PortError> {
self.as_ref().load_scoped_neighborhood(request).await
}
async fn load_context_path(
&self,
root_node_id: &str,
target_node_id: &str,
subtree_depth: u32,
) -> Result<Option<ContextPathNeighborhood>, PortError> {
self.as_ref()
.load_context_path(root_node_id, target_node_id, subtree_depth)
.await
}
}
impl<T> GraphNeighborhoodReader for &T
where
T: GraphNeighborhoodReader + Send + Sync + ?Sized,
{
fn load_nodes_batch(
&self,
node_ids: Vec<String>,
) -> impl Future<Output = Result<Vec<Option<NodeProjection>>, PortError>> + Send {
(*self).load_nodes_batch(node_ids)
}
async fn load_bounded_trace(
&self,
request: &crate::TraceSearchRequest,
) -> Result<crate::TraceSearchResult, PortError> {
(*self).load_bounded_trace(request).await
}
async fn load_evidence_paths(
&self,
request: &crate::EvidencePathRequest,
) -> Result<crate::EvidencePathResult, PortError> {
(*self).load_evidence_paths(request).await
}
async fn load_neighborhood(
&self,
root_node_id: &str,
depth: u32,
) -> Result<Option<NodeNeighborhood>, PortError> {
(*self).load_neighborhood(root_node_id, depth).await
}
async fn load_context_path(
&self,
root_node_id: &str,
target_node_id: &str,
subtree_depth: u32,
) -> Result<Option<ContextPathNeighborhood>, PortError> {
(*self)
.load_context_path(root_node_id, target_node_id, subtree_depth)
.await
}
}