use std::sync::Arc;
use axum::{
extract::State,
http::StatusCode,
response::IntoResponse,
};
use crate::http::handlers::event_normalize;
use crate::http::state::AppState;
pub async fn post_event(
State(state): State<Arc<AppState>>,
axum::Json(mut raw): axum::Json<serde_json::Value>,
) -> impl IntoResponse {
if !raw.is_object() {
return (StatusCode::BAD_REQUEST, "expected JSON object".to_string()).into_response();
}
if let Err(msg) = event_normalize::require_v2(&raw) {
return (StatusCode::BAD_REQUEST, msg.to_string()).into_response();
}
event_normalize::apply_all(&mut raw);
let event: crate::events::Event = match serde_json::from_value(raw) {
Ok(e) => e,
Err(e) => {
return (StatusCode::BAD_REQUEST, format!("invalid event: {e}")).into_response();
}
};
if event.doc.is_empty() {
return (StatusCode::BAD_REQUEST, "doc must be non-empty".to_string()).into_response();
}
let writer = Arc::clone(&state.writer);
let ev_clone = event.clone();
let write_result = tokio::task::spawn_blocking(move || writer.write(&ev_clone)).await;
let write_result = match write_result {
Ok(r) => r,
Err(e) => {
return (StatusCode::INTERNAL_SERVER_ERROR, format!("join: {e}")).into_response();
}
};
if let Err(e) = write_result {
return (StatusCode::INTERNAL_SERVER_ERROR, format!("write: {e}")).into_response();
}
let _ = state.broadcaster.send(event);
(StatusCode::NO_CONTENT, "").into_response()
}