1use std::{
2 collections::HashMap,
3 sync::{Arc, Mutex, OnceLock},
4};
5
6use anyhow::bail;
7use axum::{
8 http::StatusCode,
9 response::{IntoResponse, Response},
10};
11
12use axum_session::{Session, SessionNullPool};
13use demystify::problem::planner::PuzzlePlanner;
14use uuid::Uuid;
15
16pub struct AppError(anyhow::Error);
18
19impl IntoResponse for AppError {
21 fn into_response(self) -> Response {
22 (
23 StatusCode::INTERNAL_SERVER_ERROR,
24 format!("Something went wrong: {}", self.0),
25 )
26 .into_response()
27 }
28}
29
30impl<E> From<E> for AppError
33where
34 E: Into<anyhow::Error>,
35{
36 fn from(err: E) -> Self {
37 Self(err.into())
38 }
39}
40
41fn solver_global(
42 uuid: Uuid,
43 set_solver: Option<Arc<Mutex<PuzzlePlanner>>>,
44) -> Option<Arc<Mutex<PuzzlePlanner>>> {
45 type GlobalPuzzleStorage = Mutex<HashMap<Uuid, Arc<Mutex<PuzzlePlanner>>>>;
46 static SOLVER: OnceLock<GlobalPuzzleStorage> = OnceLock::new();
47 let m = SOLVER.get_or_init(|| Mutex::new(HashMap::new()));
48
49 if let Some(solver) = set_solver {
50 m.lock().unwrap().insert(uuid, solver);
51 None
52 } else {
53 m.lock().unwrap().get(&uuid).cloned()
54 }
55}
56
57pub fn get_solver_global(
59 session: &Session<SessionNullPool>,
60) -> anyhow::Result<Arc<Mutex<PuzzlePlanner>>> {
61 let uuid = session.get_session_id().uuid();
62 let solver = solver_global(uuid, None);
63 if let Some(solver) = solver {
64 Ok(solver)
65 } else {
66 bail!("No solver -- have you uploaded files?");
67 }
68}
69
70pub fn set_solver_global(session: &Session<SessionNullPool>, set_solver: PuzzlePlanner) {
71 let uuid = session.get_session_id().uuid();
72 solver_global(uuid, Some(Arc::new(Mutex::new(set_solver))));
73}