use super::{
classify_copy_result, owned_properties, poll_sync, property_refs, ConstraintOp, IndexOp, Wait,
WaitOperation, WaitOptions,
};
use crate::graph::vector_index_options;
use crate::{
ConstraintType, EntityType, FalkorResult, FalkorSyncClient, IndexType, LazyResultSet,
QueryResult, SyncGraph, VectorSimilarity,
};
use std::collections::HashMap;
use std::fmt::Display;
#[must_use = "an index op builder does nothing unless `.execute()` or `.wait()` is called"]
pub struct IndexOpBuilder<'a> {
graph: &'a mut SyncGraph,
op: IndexOp,
}
impl<'a> IndexOpBuilder<'a> {
pub(crate) fn new(
graph: &'a mut SyncGraph,
op: IndexOp,
) -> Self {
Self { graph, op }
}
pub fn execute(self) -> FalkorResult<QueryResult<LazyResultSet<'a>>> {
run_index_command(self.graph, &self.op)
}
pub fn wait(self) -> FalkorResult<()> {
self.wait_with(WaitOptions::default())
}
pub fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<()> {
let wait = self.op.to_wait();
run_index_command(self.graph, &self.op)?;
wait_sync(self.graph, &options, &wait)
}
}
#[must_use = "a constraint op builder does nothing unless `.execute()` or `.wait()` is called"]
pub struct ConstraintOpBuilder<'a> {
graph: &'a mut SyncGraph,
op: ConstraintOp,
}
impl<'a> ConstraintOpBuilder<'a> {
pub(crate) fn new(
graph: &'a mut SyncGraph,
op: ConstraintOp,
) -> Self {
Self { graph, op }
}
pub fn execute(self) -> FalkorResult<redis::Value> {
run_constraint_command(self.graph, &self.op)
}
pub fn wait(self) -> FalkorResult<()> {
self.wait_with(WaitOptions::default())
}
pub fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<()> {
let wait = self.op.to_wait();
run_constraint_command(self.graph, &self.op)?;
wait_sync(self.graph, &options, &wait)
}
}
#[must_use = "a copy graph builder does nothing unless `.execute()` or `.wait()` is called"]
pub struct CopyGraphBuilder<'a> {
client: &'a FalkorSyncClient,
source: String,
destination: String,
}
impl<'a> CopyGraphBuilder<'a> {
pub(crate) fn new(
client: &'a FalkorSyncClient,
source: String,
destination: String,
) -> Self {
Self {
client,
source,
destination,
}
}
pub fn execute(self) -> FalkorResult<SyncGraph> {
self.client.copy_graph(&self.source, &self.destination)
}
pub fn wait(self) -> FalkorResult<SyncGraph> {
self.wait_with(WaitOptions::for_copy())
}
pub fn wait_with(
self,
options: WaitOptions,
) -> FalkorResult<SyncGraph> {
poll_sync(&options, WaitOperation::GraphCopy, || {
Ok(classify_copy_result(
self.client.copy_graph(&self.source, &self.destination),
))
})
}
}
fn run_index_command<'a>(
graph: &'a mut SyncGraph,
op: &IndexOp,
) -> FalkorResult<QueryResult<LazyResultSet<'a>>> {
match op {
IndexOp::Create {
index_type,
entity_type,
label,
properties,
options,
} => graph.create_index(
*index_type,
*entity_type,
label,
properties,
options.as_ref(),
),
IndexOp::Drop {
index_type,
entity_type,
label,
properties,
} => graph.drop_index(*index_type, *entity_type, label, properties),
}
}
fn run_constraint_command(
graph: &mut SyncGraph,
op: &ConstraintOp,
) -> FalkorResult<redis::Value> {
match op {
ConstraintOp::CreateUnique {
entity_type,
label,
properties,
} => {
graph.create_unique_constraint(*entity_type, label.clone(), &property_refs(properties))
}
ConstraintOp::CreateMandatory {
entity_type,
label,
properties,
} => graph.create_mandatory_constraint(*entity_type, label, &property_refs(properties)),
ConstraintOp::Drop {
constraint_type,
entity_type,
label,
properties,
} => graph.drop_constraint(
*constraint_type,
*entity_type,
label,
&property_refs(properties),
),
}
}
fn wait_sync(
graph: &mut SyncGraph,
options: &WaitOptions,
wait: &Wait,
) -> FalkorResult<()> {
poll_sync(options, wait.operation(), || match wait {
Wait::Index(index_wait) => Ok(index_wait.step(&graph.list_indices()?.data)),
Wait::Constraint(constraint_wait) => {
Ok(constraint_wait.step(&graph.list_constraints()?.data))
}
})
}
impl SyncGraph {
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>>,
) -> IndexOpBuilder<'_> {
IndexOpBuilder::new(
self,
IndexOp::Create {
index_type: index_field_type,
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
options: options.cloned(),
},
)
}
pub fn create_node_vector_index_op<P: Display>(
&mut self,
label: &str,
properties: &[P],
dimension: u32,
similarity_function: VectorSimilarity,
) -> IndexOpBuilder<'_> {
IndexOpBuilder::new(
self,
IndexOp::Create {
index_type: IndexType::Vector,
entity_type: EntityType::Node,
label: label.to_string(),
properties: owned_properties(properties),
options: Some(vector_index_options(dimension, similarity_function)),
},
)
}
pub fn create_edge_vector_index_op<P: Display>(
&mut self,
relation: &str,
properties: &[P],
dimension: u32,
similarity_function: VectorSimilarity,
) -> IndexOpBuilder<'_> {
IndexOpBuilder::new(
self,
IndexOp::Create {
index_type: IndexType::Vector,
entity_type: EntityType::Edge,
label: relation.to_string(),
properties: owned_properties(properties),
options: Some(vector_index_options(dimension, similarity_function)),
},
)
}
pub fn drop_index_op<P: Display>(
&mut self,
index_field_type: IndexType,
entity_type: EntityType,
label: &str,
properties: &[P],
) -> IndexOpBuilder<'_> {
IndexOpBuilder::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],
) -> ConstraintOpBuilder<'_> {
ConstraintOpBuilder::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],
) -> ConstraintOpBuilder<'_> {
ConstraintOpBuilder::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],
) -> ConstraintOpBuilder<'_> {
ConstraintOpBuilder::new(
self,
ConstraintOp::Drop {
constraint_type,
entity_type,
label: label.to_string(),
properties: owned_properties(properties),
},
)
}
}
impl FalkorSyncClient {
pub fn copy_graph_op(
&self,
graph_to_clone: &str,
new_graph_name: &str,
) -> CopyGraphBuilder<'_> {
CopyGraphBuilder::new(self, graph_to_clone.to_string(), new_graph_name.to_string())
}
}