use axum::{
extract::{Query, State},
http::StatusCode,
response::IntoResponse,
Extension, Json,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::broadcast::Sender;
use tokio::sync::Mutex;
use terraphim_config::Config;
use terraphim_config::ConfigState;
use terraphim_rolegraph::RoleGraph;
use terraphim_service::TerraphimService;
use terraphim_types::{Document, IndexedDocument, SearchQuery};
use crate::error::{Result, Status};
pub type SearchResultsStream = Sender<IndexedDocument>;
pub(crate) async fn health() -> impl IntoResponse {
(StatusCode::OK, "OK")
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CreateDocumentResponse {
pub status: Status,
pub id: String,
}
pub(crate) async fn create_document(
State(config): State<ConfigState>,
Json(document): Json<Document>,
) -> Result<Json<CreateDocumentResponse>> {
log::debug!("create_document");
let mut terraphim_service = TerraphimService::new(config.clone());
let document = terraphim_service.create_document(document).await?;
Ok(Json(CreateDocumentResponse {
status: Status::Success,
id: document.id,
}))
}
pub(crate) async fn _list_documents(
State(rolegraph): State<Arc<Mutex<RoleGraph>>>,
) -> impl IntoResponse {
let rolegraph = rolegraph.lock().await.clone();
log::debug!("{rolegraph:?}");
(StatusCode::OK, Json("Ok"))
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SearchResponse {
pub status: Status,
pub results: Vec<Document>,
pub total: usize,
}
pub(crate) async fn search_documents(
Extension(_tx): Extension<SearchResultsStream>,
State(config_state): State<ConfigState>,
search_query: Query<SearchQuery>,
) -> Result<Json<SearchResponse>> {
log::debug!("search_document called with {:?}", search_query);
let terraphim_service = TerraphimService::new(config_state);
let results = terraphim_service.search(&search_query.0).await?;
let total = results.len();
Ok(Json(SearchResponse {
status: Status::Success,
results,
total,
}))
}
pub(crate) async fn search_documents_post(
Extension(_tx): Extension<SearchResultsStream>,
State(config_state): State<ConfigState>,
search_query: Json<SearchQuery>,
) -> Result<Json<SearchResponse>> {
log::debug!("POST Searching documents with query: {search_query:?}");
let terraphim_service = TerraphimService::new(config_state);
let results = terraphim_service.search(&search_query).await?;
let total = results.len();
if total == 0 {
log::debug!("No documents found");
} else {
log::debug!("Found {total} documents");
}
Ok(Json(SearchResponse {
status: Status::Success,
results,
total,
}))
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ConfigResponse {
pub status: Status,
pub config: Config,
}
pub(crate) async fn get_config(State(config): State<ConfigState>) -> Result<Json<ConfigResponse>> {
log::debug!("Called API endpoint get_config");
let terraphim_service = TerraphimService::new(config);
let config = terraphim_service.fetch_config().await;
Ok(Json(ConfigResponse {
status: Status::Success,
config,
}))
}
pub(crate) async fn update_config(
State(config_state): State<ConfigState>,
Json(config_new): Json<Config>,
) -> Json<ConfigResponse> {
let mut config = config_state.config.lock().await;
*config = config_new.clone();
Json(ConfigResponse {
status: Status::Success,
config: config_new,
})
}