use std::{str::FromStr, sync::Arc}; use giterated_models::{ error::OperationError, model::{instance::Instance, repository::Repository, user::User}, operation::{GiteratedObject, GiteratedOperation, Object, ObjectBackend, ObjectRequestError}, }; use sqlx::PgPool; use std::fmt::Debug; use tokio::sync::Mutex; use crate::backend::{RepositoryBackend, UserBackend}; #[derive(Clone, Debug)] pub struct Foobackend {} #[async_trait::async_trait] impl ObjectBackend for Foobackend { async fn object_operation + Debug>( &self, _object: O, _operation: D, ) -> Result> { // We don't handle operations with this backend Err(OperationError::Unhandled) } async fn get_object( &self, _object_str: &str, ) -> Result, OperationError> { todo!() } } /// A backend implementation which attempts to resolve data from the instance's database. #[derive(Clone)] pub struct DatabaseBackend<'b> { our_instance: Object<'b, Instance, Foobackend>, user_backend: Arc>, repository_backend: Arc>, pool: PgPool, } impl Debug for DatabaseBackend<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DatabaseBackend").finish() } } #[async_trait::async_trait] impl<'b> ObjectBackend for DatabaseBackend<'b> { async fn object_operation + Debug>( &self, _object: O, _operation: D, ) -> Result> { // We don't handle operations with this backend Err(OperationError::Unhandled) } async fn get_object( &self, object_str: &str, ) -> Result, OperationError> { if let Ok(user) = User::from_str(object_str) { let mut user_backend = self.user_backend.lock().await; if user_backend .exists(&user) .await .map_err(|e| OperationError::Internal(e.to_string()))? { Ok(unsafe { Object::new_unchecked( O::from_object_str(object_str) .map_err(|e| ObjectRequestError::Deserialization(e.to_string()))?, self.clone(), ) }) } else { return Err(OperationError::Unhandled); } } else if let Ok(repository) = Repository::from_str(object_str) { let mut repository_backend = self.repository_backend.lock().await; if repository_backend .exists(&repository) .await .map_err(|e| OperationError::Internal(e.to_string()))? { Ok(unsafe { Object::new_unchecked( O::from_object_str(object_str) .map_err(|e| ObjectRequestError::Deserialization(e.to_string()))?, self.clone(), ) }) } else { return Err(OperationError::Unhandled); } } else if Instance::from_str(object_str).is_ok() { return Err(OperationError::Unhandled); } else { // Invalid object type return Err(OperationError::Unhandled); } } }