use crate::serve::error::ServeError;
use crate::serve::history::catalog::{
CatalogDatasetDetail, CatalogDatasetPage, CatalogLineageEdge, CatalogListFilter,
LINEAGE_DEFAULT_DEPTH,
};
use crate::serve::state::ServerState;
use axum::Json;
use axum::extract::{Path, Query, State};
use serde::{Deserialize, Serialize};
const DEFAULT_LIMIT: usize = 100;
const MAX_LIMIT: usize = 1000;
const MAX_DEPTH: u32 = 32;
#[derive(Debug, Deserialize)]
pub struct DatasetsQuery {
pub kind: Option<String>,
pub q: Option<String>,
pub limit: Option<usize>,
pub cursor: Option<String>,
}
pub async fn list_datasets(
State(state): State<ServerState>,
Query(query): Query<DatasetsQuery>,
) -> Result<Json<CatalogDatasetPage>, ServeError> {
let filter = CatalogListFilter {
kind: query.kind,
q: query.q,
limit: query.limit.unwrap_or(DEFAULT_LIMIT).clamp(1, MAX_LIMIT),
cursor: query.cursor,
};
let page = state
.history()
.catalog_list_datasets(&filter)
.await
.map_err(|e| ServeError::Internal(e.to_string()))?;
Ok(Json(page))
}
pub async fn get_dataset(
State(state): State<ServerState>,
Path(id): Path<String>,
) -> Result<Json<CatalogDatasetDetail>, ServeError> {
let detail = state
.history()
.catalog_get_dataset(&id)
.await
.map_err(|e| ServeError::Internal(e.to_string()))?
.ok_or(ServeError::NotFound)?;
Ok(Json(detail))
}
#[derive(Debug, Deserialize)]
pub struct LineageQuery {
pub root: Option<String>,
pub depth: Option<u32>,
}
#[derive(Debug, Serialize)]
pub struct LineageResponse {
pub edges: Vec<CatalogLineageEdge>,
}
pub async fn lineage(
State(state): State<ServerState>,
Query(query): Query<LineageQuery>,
) -> Result<Json<LineageResponse>, ServeError> {
let depth = query
.depth
.unwrap_or(LINEAGE_DEFAULT_DEPTH)
.clamp(1, MAX_DEPTH);
let edges = state
.history()
.catalog_lineage(query.root.as_deref(), depth)
.await
.map_err(|e| ServeError::Internal(e.to_string()))?;
Ok(Json(LineageResponse { edges }))
}