Skip to main content

alopex_server/http/
session.rs

1use std::sync::Arc;
2
3use axum::extract::{Extension, Path};
4use axum::response::Response;
5use serde::Serialize;
6
7use crate::error::{Result, ServerError};
8use crate::http::{error_response, json_response, RequestContext};
9use crate::server::ServerState;
10use crate::session::SessionId;
11
12#[derive(Serialize)]
13struct SessionBeginResponse {
14    session_id: String,
15    expires_at: String,
16}
17
18#[derive(Serialize)]
19struct SessionActionResponse {
20    success: bool,
21}
22
23pub async fn begin(
24    Extension(state): Extension<Arc<ServerState>>,
25    Extension(ctx): Extension<RequestContext>,
26) -> Response {
27    match begin_session(state.clone()).await {
28        Ok(resp) => json_response(resp, state.config.max_response_size, &ctx),
29        Err(err) => error_response(err, &ctx),
30    }
31}
32
33pub async fn commit(
34    Extension(state): Extension<Arc<ServerState>>,
35    Extension(ctx): Extension<RequestContext>,
36    Path(id): Path<String>,
37) -> Response {
38    match session_action(state.clone(), &id, Action::Commit).await {
39        Ok(resp) => json_response(resp, state.config.max_response_size, &ctx),
40        Err(err) => error_response(err, &ctx),
41    }
42}
43
44pub async fn rollback(
45    Extension(state): Extension<Arc<ServerState>>,
46    Extension(ctx): Extension<RequestContext>,
47    Path(id): Path<String>,
48) -> Response {
49    match session_action(state.clone(), &id, Action::Rollback).await {
50        Ok(resp) => json_response(resp, state.config.max_response_size, &ctx),
51        Err(err) => error_response(err, &ctx),
52    }
53}
54
55async fn begin_session(state: Arc<ServerState>) -> Result<SessionBeginResponse> {
56    let session_id = state.session_manager.create_session().await?;
57    state.session_manager.begin_transaction(&session_id).await?;
58    let snapshot = state.session_manager.get_session(&session_id).await?;
59    let expires_at = chrono::DateTime::<chrono::Utc>::from(snapshot.expires_at);
60    Ok(SessionBeginResponse {
61        session_id: session_id.to_string(),
62        expires_at: expires_at.to_rfc3339(),
63    })
64}
65
66enum Action {
67    Commit,
68    Rollback,
69}
70
71async fn session_action(
72    state: Arc<ServerState>,
73    id: &str,
74    action: Action,
75) -> Result<SessionActionResponse> {
76    let session_id = id
77        .parse::<SessionId>()
78        .map_err(|_| ServerError::BadRequest("invalid session id".into()))?;
79    match action {
80        Action::Commit => state.session_manager.commit(&session_id).await?,
81        Action::Rollback => state.session_manager.rollback(&session_id).await?,
82    }
83    Ok(SessionActionResponse { success: true })
84}