public_appservice/
ping.rs

1use axum::{Json, extract::State, response::IntoResponse};
2
3use std::sync::Arc;
4use tokio::sync::RwLock;
5use uuid::Uuid;
6
7use serde::Deserialize;
8use serde_json::json;
9
10use crate::AppState;
11use crate::error::AppserviceError;
12
13#[derive(Debug, Clone)]
14pub struct TransactionStore {
15    current_id: Arc<RwLock<Option<String>>>,
16}
17
18impl Default for TransactionStore {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl TransactionStore {
25    pub fn new() -> Self {
26        Self {
27            current_id: Arc::new(RwLock::new(None)),
28        }
29    }
30
31    pub async fn generate_transaction_id(&self) -> String {
32        let transaction_id = Uuid::new_v4().to_string();
33        let mut store = self.current_id.write().await;
34        *store = Some(transaction_id.clone());
35        transaction_id
36    }
37
38    pub async fn verify_and_remove_transaction(&self, transaction_id: &str) -> bool {
39        let mut store = self.current_id.write().await;
40        if let Some(stored_id) = store.as_ref() {
41            if stored_id == transaction_id {
42                *store = None;
43                return true;
44            }
45        }
46        false
47    }
48}
49
50#[derive(Debug, Clone, Deserialize)]
51pub struct PingRequest {
52    pub transaction_id: String,
53}
54
55pub async fn ping(
56    State(state): State<Arc<AppState>>,
57    Json(payload): Json<PingRequest>,
58) -> Result<impl IntoResponse, AppserviceError> {
59    let txn_id = payload.transaction_id.clone();
60
61    if !state
62        .transaction_store
63        .verify_and_remove_transaction(&txn_id)
64        .await
65    {
66        tracing::info!("Transaction ID does not match: {}", txn_id);
67    }
68
69    Ok(Json(json!({})))
70}