metabase_api_rs/service/
database.rs

1//! Database Service Layer
2//!
3//! This module provides the service layer for database operations,
4//! encapsulating business logic and orchestration.
5
6use crate::core::models::database::DatabaseMetadata;
7use crate::core::models::field::Field;
8use crate::core::models::{MetabaseId, SyncResult};
9use crate::repository::database::{
10    DatabaseFilterParams, DatabaseRepository, HttpDatabaseRepository,
11};
12use crate::repository::traits::PaginationParams;
13use crate::service::traits::{Service, ServiceError, ServiceResult};
14use crate::transport::http_provider_safe::HttpProviderSafe;
15use async_trait::async_trait;
16use std::sync::Arc;
17
18/// Service trait for database operations
19#[async_trait]
20pub trait DatabaseService: Service + Send + Sync {
21    /// Get database metadata
22    async fn get_database_metadata(&self, id: MetabaseId) -> ServiceResult<DatabaseMetadata>;
23
24    /// Sync database schema
25    async fn sync_database_schema(&self, id: MetabaseId) -> ServiceResult<SyncResult>;
26
27    /// Get database fields
28    async fn get_database_fields(&self, id: MetabaseId) -> ServiceResult<Vec<Field>>;
29
30    /// Get database schemas
31    async fn get_database_schemas(&self, id: MetabaseId) -> ServiceResult<Vec<String>>;
32
33    /// List databases
34    async fn list_databases(
35        &self,
36        pagination: Option<PaginationParams>,
37        filters: Option<DatabaseFilterParams>,
38    ) -> ServiceResult<Vec<DatabaseMetadata>>;
39
40    /// Validate database ID
41    async fn validate_database_id(&self, id: MetabaseId) -> ServiceResult<()>;
42}
43
44/// HTTP implementation of DatabaseService
45pub struct HttpDatabaseService {
46    repository: Arc<dyn DatabaseRepository>,
47}
48
49impl HttpDatabaseService {
50    /// Creates a new HttpDatabaseService
51    pub fn new(repository: Arc<dyn DatabaseRepository>) -> Self {
52        Self { repository }
53    }
54
55    /// Creates a new HttpDatabaseService from HTTP provider
56    pub fn from_http_provider(http_provider: Arc<dyn HttpProviderSafe>) -> Self {
57        let repository = Arc::new(HttpDatabaseRepository::new(http_provider));
58        Self { repository }
59    }
60}
61
62#[async_trait]
63impl Service for HttpDatabaseService {
64    fn name(&self) -> &str {
65        "DatabaseService"
66    }
67}
68
69#[async_trait]
70impl DatabaseService for HttpDatabaseService {
71    async fn get_database_metadata(&self, id: MetabaseId) -> ServiceResult<DatabaseMetadata> {
72        // Validate database ID
73        self.validate_database_id(id).await?;
74
75        // Get metadata from repository
76        self.repository
77            .get(&id)
78            .await
79            .map_err(ServiceError::Repository)
80    }
81
82    async fn sync_database_schema(&self, id: MetabaseId) -> ServiceResult<SyncResult> {
83        // Validate database ID
84        self.validate_database_id(id).await?;
85
86        // Sync schema through repository
87        self.repository
88            .sync_database_schema(&id)
89            .await
90            .map_err(ServiceError::Repository)
91    }
92
93    async fn get_database_fields(&self, id: MetabaseId) -> ServiceResult<Vec<Field>> {
94        // Validate database ID
95        self.validate_database_id(id).await?;
96
97        // Get fields from repository
98        self.repository
99            .get_database_fields(&id)
100            .await
101            .map_err(ServiceError::Repository)
102    }
103
104    async fn get_database_schemas(&self, id: MetabaseId) -> ServiceResult<Vec<String>> {
105        // Validate database ID
106        self.validate_database_id(id).await?;
107
108        // Get schemas from repository
109        self.repository
110            .get_database_schemas(&id)
111            .await
112            .map_err(ServiceError::Repository)
113    }
114
115    async fn list_databases(
116        &self,
117        pagination: Option<PaginationParams>,
118        filters: Option<DatabaseFilterParams>,
119    ) -> ServiceResult<Vec<DatabaseMetadata>> {
120        // List databases from repository
121        self.repository
122            .list_with_filters(pagination, filters)
123            .await
124            .map_err(ServiceError::Repository)
125    }
126
127    async fn validate_database_id(&self, id: MetabaseId) -> ServiceResult<()> {
128        if id.0 < 1 {
129            return Err(ServiceError::Validation(
130                "Invalid database ID: must be positive".to_string(),
131            ));
132        }
133        Ok(())
134    }
135}