use crate::model::responses::{NearestTileResponse, TileResponse}; use axum::Error; use chrono::{DateTime, Utc}; use sqlx::PgPool; #[derive(Clone)] pub struct Service { pub pool: PgPool, } impl Service { pub fn new(pool: PgPool) -> Self { Self { pool } } pub async fn get_tile_data( &self, datetime: DateTime, area: &str, ) -> Result { let primitive_datetime = datetime.format("%Y%m%d%H%M%S").to_string(); let record = sqlx::query!( r#" SELECT id, ingestion_time, data_time, source, storage_url FROM data_ingestion WHERE data_time = $1 AND source = $2 "#, datetime.naive_utc(), area ) .fetch_optional(&self.pool) .await .map_err(|e| Error::new(format!("Database error: {}", e)))?; match record { Some(row) => Ok(TileResponse { id: row.id, ingestion_time: row.ingestion_time.and_utc(), data_time: row.data_time.and_utc(), source: row.source, storage_url: row.storage_url, }), None => Err(Error::new(format!( "No tile data found for datetime: {} and area: {}", primitive_datetime, area ))), } } pub async fn get_nearest_tile_data( &self, datetime: DateTime, area: &str, ) -> Result { let primitive_datetime = datetime.format("%Y%m%d%H%M%S").to_string(); // 查找距离指定 datetime 最近的数据 let record = sqlx::query!( r#" SELECT id, data_time FROM data_ingestion WHERE source = $1 ORDER BY ABS(EXTRACT(EPOCH FROM (data_time - $2))) LIMIT 1 "#, area, datetime.naive_utc() ) .fetch_optional(&self.pool) .await .map_err(|e| Error::new(format!("Database error: {}", e)))?; match record { Some(row) => Ok(NearestTileResponse { id: row.id, nearest_data_time: row.data_time.and_utc(), }), None => Err(Error::new(format!("No tile data found for area: {}", area))), } } }