use diesel::prelude::*;
use super::AdminServiceStoreOperations;
use crate::admin::store::{
diesel::{
models::{ServiceArgumentModel, ServiceModel},
schema::{service, service_argument},
},
error::AdminServiceStoreError,
Service, ServiceBuilder, ServiceId,
};
pub(in crate::admin::store::diesel) trait AdminServiceStoreFetchServiceOperation {
fn get_service(
&self,
service_id: &ServiceId,
) -> Result<Option<Service>, AdminServiceStoreError>;
}
impl<'a, C> AdminServiceStoreFetchServiceOperation for AdminServiceStoreOperations<'a, C>
where
C: diesel::Connection,
String: diesel::deserialize::FromSql<diesel::sql_types::Text, C::Backend>,
i64: diesel::deserialize::FromSql<diesel::sql_types::BigInt, C::Backend>,
i32: diesel::deserialize::FromSql<diesel::sql_types::Integer, C::Backend>,
{
fn get_service(
&self,
service_id: &ServiceId,
) -> Result<Option<Service>, AdminServiceStoreError> {
self.conn.transaction::<Option<Service>, _, _>(|| {
let service: ServiceModel = match service::table
.filter(service::circuit_id.eq(&service_id.circuit_id))
.filter(service::service_id.eq(&service_id.service_id))
.first::<ServiceModel>(self.conn)
.optional()?
{
Some(service) => service,
None => return Ok(None),
};
let arguments: Vec<(String, String)> = service_argument::table
.filter(service_argument::circuit_id.eq(&service_id.circuit_id))
.filter(service_argument::service_id.eq(&service_id.service_id))
.order(service_argument::position)
.load::<ServiceArgumentModel>(self.conn)?
.iter()
.map(|arg| (arg.key.to_string(), arg.value.to_string()))
.collect();
let return_service = ServiceBuilder::new()
.with_service_id(&service.service_id)
.with_service_type(&service.service_type)
.with_arguments(&arguments)
.with_node_id(&service.node_id)
.build()
.map_err(AdminServiceStoreError::InvalidStateError)?;
Ok(Some(return_service))
})
}
}