use diesel::prelude::*;
use diesel::sql_types::{Binary, Integer, Nullable, Text};
use super::AdminServiceStoreOperations;
use crate::admin::store::{
diesel::{
models::{CircuitMemberModel, NodeEndpointModel},
schema::{circuit_member, node_endpoint},
},
error::AdminServiceStoreError,
CircuitNode, CircuitNodeBuilder,
};
pub(in crate::admin::store::diesel) trait AdminServiceStoreFetchNodeOperation {
fn get_node(&self, node_id: &str) -> Result<Option<CircuitNode>, AdminServiceStoreError>;
}
impl<'a, C> AdminServiceStoreFetchNodeOperation for AdminServiceStoreOperations<'a, C>
where
C: diesel::Connection,
String: diesel::deserialize::FromSql<Text, C::Backend>,
i64: diesel::deserialize::FromSql<diesel::sql_types::BigInt, C::Backend>,
i32: diesel::deserialize::FromSql<Integer, C::Backend>,
CircuitMemberModel: diesel::Queryable<(Text, Text, Integer, Nullable<Binary>), C::Backend>,
{
fn get_node(&self, node_id: &str) -> Result<Option<CircuitNode>, AdminServiceStoreError> {
self.conn.transaction::<Option<CircuitNode>, _, _>(|| {
let member: CircuitMemberModel = match circuit_member::table
.filter(circuit_member::node_id.eq(&node_id))
.first::<CircuitMemberModel>(self.conn)
.optional()?
{
Some(node) => node,
None => return Ok(None),
};
let endpoints: Vec<String> = node_endpoint::table
.filter(node_endpoint::node_id.eq(&member.node_id))
.load(self.conn)?
.into_iter()
.map(|endpoint_model: NodeEndpointModel| endpoint_model.endpoint)
.collect();
Ok(Some(
CircuitNodeBuilder::new()
.with_node_id(&member.node_id)
.with_endpoints(&endpoints)
.build()
.map_err(AdminServiceStoreError::InvalidStateError)?,
))
})
}
}