use diesel::{dsl::insert_into, prelude::*};
use crate::error::InvalidStateError;
use crate::registry::{
diesel::{
models::{NodeEndpointsModel, NodeKeysModel, NodeMetadataModel, NodesModel},
schema::{
splinter_nodes, splinter_nodes_endpoints, splinter_nodes_keys, splinter_nodes_metadata,
},
},
Node, RegistryError,
};
use super::RegistryOperations;
pub(in crate::registry::diesel) trait RegistryAddNodeOperation {
fn add_node(&self, node: Node) -> Result<(), RegistryError>;
}
#[cfg(feature = "postgres")]
impl<'a> RegistryAddNodeOperation for RegistryOperations<'a, diesel::pg::PgConnection> {
fn add_node(&self, node: Node) -> Result<(), RegistryError> {
self.conn.transaction::<(), _, _>(|| {
let filters = node
.endpoints
.iter()
.map(|endpoint| endpoint.to_string())
.collect::<Vec<_>>();
let duplicate_endpoint = splinter_nodes_endpoints::table
.filter(splinter_nodes_endpoints::endpoint.eq_any(filters))
.first::<NodeEndpointsModel>(self.conn)
.optional()?;
if let Some(endpoint) = duplicate_endpoint {
return Err(RegistryError::InvalidStateError(
InvalidStateError::with_message(format!(
"another node with endpoint {} exists",
endpoint.endpoint
)),
));
}
insert_into(splinter_nodes::table)
.values(NodesModel::from(&node))
.execute(self.conn)?;
let endpoints: Vec<NodeEndpointsModel> = Vec::from(&node);
insert_into(splinter_nodes_endpoints::table)
.values(&endpoints)
.execute(self.conn)?;
let keys: Vec<NodeKeysModel> = Vec::from(&node);
insert_into(splinter_nodes_keys::table)
.values(&keys)
.execute(self.conn)?;
let metadata: Vec<NodeMetadataModel> = Vec::from(&node);
insert_into(splinter_nodes_metadata::table)
.values(&metadata)
.execute(self.conn)?;
Ok(())
})
}
}
#[cfg(feature = "sqlite")]
impl<'a> RegistryAddNodeOperation for RegistryOperations<'a, diesel::sqlite::SqliteConnection> {
fn add_node(&self, node: Node) -> Result<(), RegistryError> {
self.conn.transaction::<(), _, _>(|| {
let filters = node
.endpoints
.iter()
.map(|endpoint| endpoint.to_string())
.collect::<Vec<_>>();
let duplicate_endpoint = splinter_nodes_endpoints::table
.filter(splinter_nodes_endpoints::endpoint.eq_any(filters))
.first::<NodeEndpointsModel>(self.conn)
.optional()?;
if let Some(endpoint) = duplicate_endpoint {
return Err(RegistryError::InvalidStateError(
InvalidStateError::with_message(format!(
"another node with endpoint {} exists",
endpoint.endpoint
)),
));
}
insert_into(splinter_nodes::table)
.values(NodesModel::from(&node))
.execute(self.conn)?;
let endpoints: Vec<NodeEndpointsModel> = Vec::from(&node);
insert_into(splinter_nodes_endpoints::table)
.values(&endpoints)
.execute(self.conn)?;
let keys: Vec<NodeKeysModel> = Vec::from(&node);
insert_into(splinter_nodes_keys::table)
.values(&keys)
.execute(self.conn)?;
let metadata: Vec<NodeMetadataModel> = Vec::from(&node);
insert_into(splinter_nodes_metadata::table)
.values(&metadata)
.execute(self.conn)?;
Ok(())
})
}
}