use actix_web::{web, web::Json, Error, HttpResponse, Result}; use futures::Future; use lootalot_db::Pool; use lootalot_db::{ActionResult, DbConnection, Item, Player, QueryResult}; pub struct DbApi<'q>(&'q DbConnection); impl<'q> DbApi<'q> { pub fn with_conn(conn: &'q DbConnection) -> Self { Self(conn) } pub fn fetch_players(self) -> QueryResult> { Player::fetch_list(self.0) } pub fn as_player(self, id: i32) -> AsPlayer<'q> { AsPlayer { id, conn: self.0 } } } pub struct AsPlayer<'q> { id: i32, conn: &'q DbConnection, } impl<'q> AsPlayer<'q> { /// Fetch the content of a player's chest pub fn loot(self) -> QueryResult> { Player::fetch_loot(self.id, self.conn) } pub fn claim(self, item: i32) -> ActionResult { Player::action_claim_object(self.id, item, self.conn) } } // struct DbApi<'q>(&'q DbConnection); // ::new() -> DbApi<'q> (Db finds a connection by itself, usefull for cli) // ::with_conn(conn) -> DbApi<'q> (uses a user-defined connection) // .fetch_players() // .with_player(player_id) -> AsPlayer<'q> // .loot() -> List of items owned (Vec) // .claim(item_id) -> Success status (bool) // .unclaim(item_id) -> Success status (bool) // .sell(item_id) -> Success status (bool, earned) // .income(wealth_data) -> Success status (bool, new_wealth) // .with_admin() // .resolve_claims() // // fn db_call(f: fn(DbApi) -> ApiResponse) { ... } // ApiResponse needs to be Serialize pub fn db_call< J: serde::ser::Serialize + Send + 'static, Q: Fn(DbApi) -> QueryResult + Send + 'static, >( pool: web::Data, query: Q, ) -> impl Future { let conn = pool.get().unwrap(); web::block(move || { let api = DbApi::with_conn(&conn); query(api) }) .then(|res| match res { Ok(players) => HttpResponse::Ok().json(players), Err(e) => { dbg!(&e); HttpResponse::InternalServerError().finish() } }) }