use crate::authz::KbAccess;
use crate::error::{ApiError, ApiErrorResponse};
use crate::middleware::extract_request_id;
use crate::state::AppState;
use axum::Json;
use axum::extract::{Path, Request, State};
use axum::http::{StatusCode, header};
use axum::response::{IntoResponse, Response};
use serde::Serialize;
#[derive(Serialize)]
struct ReconcileStarted<'a> {
kb_slug: &'a str,
status: &'static str,
}
pub(super) async fn post_index_reconcile(
State(state): State<AppState>,
Path(kb_slug): Path<String>,
req: Request,
) -> Result<Response, ApiErrorResponse> {
let request_id = extract_request_id(&req);
let err = |error: ApiError| ApiErrorResponse {
error,
request_id: request_id.clone(),
};
let access = KbAccess::resolve(&state, &kb_slug, &req).map_err(&err)?;
access.require_service_token().map_err(&err)?;
let trigger = state
.reconcile
.as_ref()
.ok_or(ApiError::ReconcileUnsupported)
.map_err(&err)?;
trigger
.trigger(access.kb())
.map_err(|_busy| err(ApiError::ReconcileInProgress))?;
tracing::info!(
target: "notedthat::reconcile",
kb = %access.kb().as_str(),
"reconciliation requested"
);
Ok((
StatusCode::ACCEPTED,
[(header::CACHE_CONTROL, "no-store")],
Json(ReconcileStarted {
kb_slug: access.kb().as_str(),
status: "started",
}),
)
.into_response())
}