use diesel::{
dsl::{delete, insert_into, not, update},
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 RegistryUpdateNodeOperation {
fn update_node(&self, node: Node) -> Result<(), RegistryError>;
}
#[cfg(feature = "postgres")]
impl<'a> RegistryUpdateNodeOperation for RegistryOperations<'a, diesel::pg::PgConnection> {
fn update_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))
.filter(not(splinter_nodes_endpoints::identity.eq(&node.identity)))
.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
)),
));
}
let existing_node = splinter_nodes::table
.find(&node.identity)
.first::<NodesModel>(self.conn)
.optional()?;
if existing_node.is_some() {
update(splinter_nodes::table.find(&node.identity))
.set(splinter_nodes::display_name.eq(&node.display_name))
.execute(self.conn)?;
delete(
splinter_nodes_endpoints::table
.filter(splinter_nodes_endpoints::identity.eq(&node.identity)),
)
.execute(self.conn)?;
delete(
splinter_nodes_keys::table
.filter(splinter_nodes_keys::identity.eq(&node.identity)),
)
.execute(self.conn)?;
delete(
splinter_nodes_metadata::table
.filter(splinter_nodes_metadata::identity.eq(&node.identity)),
)
.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(())
} else {
Err(RegistryError::InvalidStateError(
InvalidStateError::with_message(format!(
"Node does not exist: {}",
&node.identity
)),
))
}
})
}
}
#[cfg(feature = "sqlite")]
impl<'a> RegistryUpdateNodeOperation for RegistryOperations<'a, diesel::sqlite::SqliteConnection> {
fn update_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))
.filter(not(splinter_nodes_endpoints::identity.eq(&node.identity)))
.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
)),
));
}
let existing_node = splinter_nodes::table
.find(&node.identity)
.first::<NodesModel>(self.conn)
.optional()?;
if existing_node.is_some() {
update(splinter_nodes::table.find(&node.identity))
.set(splinter_nodes::display_name.eq(&node.display_name))
.execute(self.conn)?;
delete(
splinter_nodes_endpoints::table
.filter(splinter_nodes_endpoints::identity.eq(&node.identity)),
)
.execute(self.conn)?;
delete(
splinter_nodes_keys::table
.filter(splinter_nodes_keys::identity.eq(&node.identity)),
)
.execute(self.conn)?;
delete(
splinter_nodes_metadata::table
.filter(splinter_nodes_metadata::identity.eq(&node.identity)),
)
.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(())
} else {
Err(RegistryError::InvalidStateError(
InvalidStateError::with_message(format!(
"Node does not exist: {}",
&node.identity
)),
))
}
})
}
}