try out a generic ApiResponse

This commit is contained in:
2019-10-15 16:22:46 +02:00
parent 6101aaa9e9
commit 8af7790d17

View File

@@ -4,11 +4,30 @@ use actix_web::{web, App, Error, HttpResponse, HttpServer};
use futures::Future;
use lootalot_db::{DbApi, Pool, QueryResult};
use lootalot_db::{Item, LootManager};
use lootalot_db as db;
use serde::{Deserialize, Serialize};
use std::env;
use std::default;
type AppPool = web::Data<Pool>;
#[derive(Serialize, Deserialize, Debug)]
enum Update {
NoUpdate,
Wealth,
ItemAdded,
ItemRemoved,
ClaimAdded,
ClaimRemoved,
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct ApiResponse<T> {
value: Option<T>, // The value requested, if any
notify: Option<String>, // A text to notify user, if relevant
updates: Option<Vec<Update>>, // A list of updates, if any
errors: Option<String>, // A text describing errors, if any
}
/// Wraps call to the DbApi and process its result as a async HttpResponse
///
/// Provides a convenient way to call the api inside a route definition. Given a connection pool,
@@ -33,7 +52,7 @@ type AppPool = web::Data<Pool>;
pub fn db_call<J, Q>(pool: AppPool, query: Q) -> impl Future<Item = HttpResponse, Error = Error>
where
J: serde::ser::Serialize + Send + 'static,
Q: Fn(DbConnection) -> QueryResult<J> + Send + 'static,
Q: Fn(DbConnection) -> ApiResponse<J> + Send + 'static,
{
let conn = pool.get().unwrap();
web::block(move || query(conn)).then(|res| match res {
@@ -74,23 +93,54 @@ mod endpoints {
}
pub fn players_list(pool: AppPool) -> impl Future<Item = HttpResponse, Error = Error> {
db_call(pool, move |api| api.fetch_players())
db_call(pool, move |conn| {
let (value, errors) = match db::Players(conn).all() {
Ok(v) => (Some(v), None),
Err(e) => (None, Some(e.to_string())),
};
ApiResponse {
value,
errors,
..Default::default()
}
})
}
pub fn player_loot(
pool: AppPool,
player_id: web::Path<i32>,
) -> impl Future<Item = HttpResponse, Error = Error> {
db_call(pool, move |conn| LootManager(&conn, *player_id).all())
db_call(pool, move |conn| {
let (value, errors) = {
match db::LootManager(&conn, *player_id).all() {
Ok(v) => (Some(v), None),
Err(e) => (None, Some(e.to_string())),
}
};
ApiResponse {
value,
errors,
..Default::default()
}
})
}
pub fn update_wealth(
pool: AppPool,
data: web::Json<WealthUpdate>,
(player, data): (web::Path<i32>, web::Json<WealthUpdate>),
) -> impl Future<Item = HttpResponse, Error = Error> {
db_call(pool, move |api| {
api.as_player(data.player_id)
.update_wealth(data.value_in_gp)
db_call(pool, move |conn| {
let (updates, errors) =
match db::AsPlayer(conn, player)
.update_wealth(data.value_in_gp) {
Ok(w) => (Some(vec![w.as_tuple(),]), None),
Err(e) => (None, Some(e.to_string())),
};
ApiResponse {
updates,
errors,
..Default::default()
}
})
}