Archived
feat: schema projections, command transactions, quantum-secure encryption
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
/// Transaction API routes.
|
||||
///
|
||||
/// POST /tx/apply — apply a command
|
||||
/// POST /tx/rollback/{id} — roll back a command
|
||||
/// GET /tx/history?since={ms} — command history
|
||||
/// GET /tx/chain/{id} — causal chain for a command
|
||||
use axum::{
|
||||
extract::{Path, Query, State},
|
||||
http::StatusCode,
|
||||
Json,
|
||||
};
|
||||
use engram_tx::{Command, CommandResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
// ── POST /tx/apply ────────────────────────────────────────────────────────────
|
||||
|
||||
pub async fn tx_apply(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(cmd): Json<Command>,
|
||||
) -> Result<Json<CommandResult>, StatusCode> {
|
||||
let mut engine = state
|
||||
.tx_engine
|
||||
.lock()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
let result = engine
|
||||
.apply(cmd)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
// ── POST /tx/rollback/{command_id} ───────────────────────────────────────────
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RollbackResponse {
|
||||
pub rollback_command_id: Uuid,
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
pub async fn tx_rollback(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(command_id): Path<Uuid>,
|
||||
) -> Result<Json<RollbackResponse>, StatusCode> {
|
||||
let mut engine = state
|
||||
.tx_engine
|
||||
.lock()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
let rb = engine
|
||||
.rollback(command_id)
|
||||
.map_err(|e| {
|
||||
tracing::warn!("rollback failed: {}", e);
|
||||
StatusCode::BAD_REQUEST
|
||||
})?;
|
||||
Ok(Json(RollbackResponse {
|
||||
rollback_command_id: rb.id,
|
||||
status: format!("{:?}", rb.status),
|
||||
}))
|
||||
}
|
||||
|
||||
// ── GET /tx/history ───────────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct HistoryParams {
|
||||
pub since: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct HistoryResponse {
|
||||
pub commands: Vec<Command>,
|
||||
}
|
||||
|
||||
pub async fn tx_history(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Query(params): Query<HistoryParams>,
|
||||
) -> Result<Json<HistoryResponse>, StatusCode> {
|
||||
let engine = state
|
||||
.tx_engine
|
||||
.lock()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
let since = params.since.unwrap_or(0);
|
||||
let commands = engine
|
||||
.history(since)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
Ok(Json(HistoryResponse { commands }))
|
||||
}
|
||||
|
||||
// ── GET /tx/chain/{command_id} ────────────────────────────────────────────────
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CausalChainResponse {
|
||||
pub chain: Vec<Command>,
|
||||
}
|
||||
|
||||
pub async fn tx_causal_chain(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(command_id): Path<Uuid>,
|
||||
) -> Result<Json<CausalChainResponse>, StatusCode> {
|
||||
let engine = state
|
||||
.tx_engine
|
||||
.lock()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
let chain = engine
|
||||
.causal_chain(command_id)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
Ok(Json(CausalChainResponse { chain }))
|
||||
}
|
||||
Reference in New Issue
Block a user