use super::{
classify_copy_result, owned_properties, poll_async, property_refs, ConstraintOp, IndexOp, Step,
Wait, WaitOperation, WaitOptions,
};
use crate::{
AsyncGraph, ConstraintType, EntityType, FalkorAsyncClient, FalkorResult, IndexType,
QueryResult, RowStream,
};
use std::collections::HashMap;
use std::fmt::Display;
#[must_use = "an index op builder does nothing unless `.execute()` or `.wait()` is awaited"]
pub struct AsyncIndexOpBuilder<'a> {
graph: &'a mut AsyncGraph,
op: IndexOp,
}
impl<'a> AsyncIndexOpBuilder<'a> {
pub(crate) fn new(
graph: &'a mut AsyncGraph,
op: IndexOp,
) -> Self {
Self { graph, op }
}
pub async fn execute(self) -> FalkorResult<QueryResult<RowStream>> {
run_index_command(self.graph, &self.op).await
}
pub async fn wait(self) -> FalkorResult<()> {
self.wait_with(WaitOptions::default()).await
}
pub async fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<()> {
let wait = self.op.to_wait();
run_index_command(self.graph, &self.op).await?;
wait_async(self.graph, &options, wait).await
}
}
#[must_use = "a constraint op builder does nothing unless `.execute()` or `.wait()` is awaited"]
pub struct AsyncConstraintOpBuilder<'a> {
graph: &'a mut AsyncGraph,
op: ConstraintOp,
}
impl<'a> AsyncConstraintOpBuilder<'a> {
pub(crate) fn new(
graph: &'a mut AsyncGraph,
op: ConstraintOp,
) -> Self {
Self { graph, op }
}
pub async fn execute(self) -> FalkorResult<redis::Value> {
run_constraint_command(self.graph, &self.op).await
}
pub async fn wait(self) -> FalkorResult<()> {
self.wait_with(WaitOptions::default()).await
}
pub async fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<()> {
let wait = self.op.to_wait();
run_constraint_command(self.graph, &self.op).await?;
wait_async(self.graph, &options, wait).await
}
}
#[must_use = "a copy graph builder does nothing unless `.execute()` or `.wait()` is awaited"]
pub struct AsyncCopyGraphBuilder<'a> {
client: &'a FalkorAsyncClient,
source: String,
destination: String,
}
impl<'a> AsyncCopyGraphBuilder<'a> {
pub(crate) fn new(
client: &'a FalkorAsyncClient,
source: String,
destination: String,
) -> Self {
Self {
client,
source,
destination,
}
}
pub async fn execute(self) -> FalkorResult<AsyncGraph> {
self.client
.copy_graph(&self.source, &self.destination)
.await
}
pub async fn wait(self) -> FalkorResult<AsyncGraph> {
self.wait_with(WaitOptions::for_copy()).await
}
pub async fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<AsyncGraph> {
let mut this = self;
poll_async(&mut this, &options, WaitOperation::GraphCopy, |this| {
Box::pin(async move {
Ok(classify_copy_result(
this.client
.copy_graph(&this.source, &this.destination)
.await,
))
})
})
.await
}
}
async fn run_index_command(
graph: &mut AsyncGraph,
op: &IndexOp,
) -> FalkorResult<QueryResult<RowStream>> {
match op {
IndexOp::Create {
index_type,
entity_type,
label,
properties,
options,
} => {
graph
.create_index(
*index_type,
*entity_type,
label,
properties,
options.as_ref(),
)
.await
}
IndexOp::Drop {
index_type,
entity_type,
label,
properties,
} => {
graph
.drop_index(*index_type, *entity_type, label, properties)
.await
}
}
}
async fn run_constraint_command(
graph: &mut AsyncGraph,
op: &ConstraintOp,
) -> FalkorResult<redis::Value> {
match op {
ConstraintOp::CreateUnique {
entity_type,
label,
properties,
} => {
graph
.create_unique_constraint(*entity_type, label.clone(), &property_refs(properties))
.await
}
ConstraintOp::CreateMandatory {
entity_type,
label,
properties,
} => {
graph
.create_mandatory_constraint(*entity_type, label, &property_refs(properties))
.await
}
ConstraintOp::Drop {
constraint_type,
entity_type,
label,
properties,
} => {
graph
.drop_constraint(
*constraint_type,
*entity_type,
label,
&property_refs(properties),
)
.await
}
}
}
async fn evaluate_async(
graph: &mut AsyncGraph,
wait: &Wait,
) -> FalkorResult<Step<()>> {
match wait {
Wait::Index(index_wait) => Ok(index_wait.step(&graph.list_indices().await?.data)),
Wait::Constraint(constraint_wait) => {
Ok(constraint_wait.step(&graph.list_constraints().await?.data))
}
}
}
async fn wait_async(
graph: &mut AsyncGraph,
options: &WaitOptions,
wait: Wait,
) -> FalkorResult<()> {
let operation = wait.operation();
let mut state = (graph, wait);
poll_async(&mut state, options, operation, |state| {
let (graph, wait) = state;
Box::pin(evaluate_async(graph, wait))
})
.await
}
impl AsyncGraph {
pub fn create_index_op<P: Display>(
&mut self,
index_field_type: IndexType,
entity_type: EntityType,
label: &str,
properties: &[P],
options: Option<&HashMap<String, String>>,
) -> AsyncIndexOpBuilder<'_> {
AsyncIndexOpBuilder::new(
self,
IndexOp::Create {
index_type: index_field_type,
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
options: options.cloned(),
},
)
}
pub fn drop_index_op<P: Display>(
&mut self,
index_field_type: IndexType,
entity_type: EntityType,
label: &str,
properties: &[P],
) -> AsyncIndexOpBuilder<'_> {
AsyncIndexOpBuilder::new(
self,
IndexOp::Drop {
index_type: index_field_type,
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
},
)
}
pub fn create_unique_constraint_op(
&mut self,
entity_type: EntityType,
label: &str,
properties: &[&str],
) -> AsyncConstraintOpBuilder<'_> {
AsyncConstraintOpBuilder::new(
self,
ConstraintOp::CreateUnique {
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
},
)
}
pub fn create_mandatory_constraint_op(
&mut self,
entity_type: EntityType,
label: &str,
properties: &[&str],
) -> AsyncConstraintOpBuilder<'_> {
AsyncConstraintOpBuilder::new(
self,
ConstraintOp::CreateMandatory {
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
},
)
}
pub fn drop_constraint_op(
&mut self,
constraint_type: ConstraintType,
entity_type: EntityType,
label: &str,
properties: &[&str],
) -> AsyncConstraintOpBuilder<'_> {
AsyncConstraintOpBuilder::new(
self,
ConstraintOp::Drop {
constraint_type,
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
},
)
}
}
impl FalkorAsyncClient {
pub fn copy_graph_op(
&self,
graph_to_clone: &str,
new_graph_name: &str,
) -> AsyncCopyGraphBuilder<'_> {
AsyncCopyGraphBuilder::new(self, graph_to_clone.to_string(), new_graph_name.to_string())
}
}