tx handled outside of rpc calls

This commit is contained in:
ntr 2018-10-15 15:55:50 +11:00
parent b83ab923c4
commit 63bae0e0e5
5 changed files with 54 additions and 60 deletions

View File

@ -5,6 +5,8 @@ use rand::distributions::Alphanumeric;
use std::iter; use std::iter;
use serde_cbor::{from_slice}; use serde_cbor::{from_slice};
use postgres::transaction::Transaction;
use std::str; use std::str;
use net::Db; use net::Db;
@ -35,14 +37,14 @@ struct AccountEntry {
// MAYBE // MAYBE
// hash tokens with a secret // hash tokens with a secret
pub fn account_from_token(token: String, db: &Db) -> Result<Account, Error> { pub fn account_from_token(token: String, tx: &mut Transaction) -> Result<Account, Error> {
let query = " let query = "
SELECT id, name, token SELECT id, name, token
FROM accounts FROM accounts
WHERE token = $1; WHERE token = $1;
"; ";
let result = db let result = tx
.query(query, &[&token])?; .query(query, &[&token])?;
let returned = match result.iter().next() { let returned = match result.iter().next() {
@ -59,7 +61,7 @@ pub fn account_from_token(token: String, db: &Db) -> Result<Account, Error> {
return Ok(entry); return Ok(entry);
} }
pub fn account_create(params: AccountCreateParams, db: &Db) -> Result<Account, Error> { pub fn account_create(params: AccountCreateParams, tx: &mut Transaction) -> Result<Account, Error> {
let id = Uuid::new_v4(); let id = Uuid::new_v4();
if params.password.len() < PASSWORD_MIN_LEN { if params.password.len() < PASSWORD_MIN_LEN {
@ -86,7 +88,6 @@ pub fn account_create(params: AccountCreateParams, db: &Db) -> Result<Account, E
RETURNING id, name, token; RETURNING id, name, token;
"; ";
let mut tx = db.transaction()?;
let result = tx let result = tx
.query(query, &[&account.id, &account.name, &account.password, &account.token])?; .query(query, &[&account.id, &account.name, &account.password, &account.token])?;
@ -103,21 +104,20 @@ pub fn account_create(params: AccountCreateParams, db: &Db) -> Result<Account, E
// give them a revive // give them a revive
let revive = Item::new(ItemAction::Revive, &entry); let revive = Item::new(ItemAction::Revive, &entry);
item_create(revive, &mut tx, &entry)?; item_create(revive, tx, &entry)?;
tx.commit()?;
return Ok(entry); return Ok(entry);
} }
pub fn account_login(params: AccountLoginParams, db: &Db) -> Result<Account, Error> { pub fn account_login(params: AccountLoginParams, tx: &mut Transaction) -> Result<Account, Error> {
let query = " let query = "
SELECT id, name, token, password SELECT id, name, token, password
FROM accounts FROM accounts
WHERE name = $1; WHERE name = $1;
"; ";
let result = db let result = tx
.query(query, &[&params.name])?; .query(query, &[&params.name])?;
let returned = match result.iter().next() { let returned = match result.iter().next() {
@ -153,14 +153,14 @@ pub fn account_login(params: AccountLoginParams, db: &Db) -> Result<Account, Err
return Ok(account); return Ok(account);
} }
pub fn account_cryps(db: &Db, account: &Account) -> Result<Vec<Cryp>, Error> { pub fn account_cryps(tx: &mut Transaction, account: &Account) -> Result<Vec<Cryp>, Error> {
let query = " let query = "
SELECT data SELECT data
FROM cryps FROM cryps
WHERE account = $1; WHERE account = $1;
"; ";
let result = db let result = tx
.query(query, &[&account.id])?; .query(query, &[&account.id])?;
let cryps: Result<Vec<Cryp>, _> = result.iter().map(|row| { let cryps: Result<Vec<Cryp>, _> = result.iter().map(|row| {

View File

@ -2,10 +2,10 @@ use rand::prelude::*;
use serde_cbor::{from_slice}; use serde_cbor::{from_slice};
// Db Commons // Db Commons
use postgres::transaction::Transaction;
use failure::Error; use failure::Error;
use failure::err_msg; use failure::err_msg;
use net::Db;
use account::Account; use account::Account;
use rpc::{CombatPveParams}; use rpc::{CombatPveParams};
@ -92,7 +92,7 @@ fn generate_mob(plr: &Cryp) -> Cryp {
} }
pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle, Error> { pub fn pve(params: CombatPveParams, tx: &mut Transaction, account: &Account) -> Result<Battle, Error> {
let query = " let query = "
SELECT * SELECT *
FROM cryps FROM cryps
@ -100,8 +100,6 @@ pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle
AND account = $2; AND account = $2;
"; ";
let mut tx = db.transaction()?;
let result = tx let result = tx
.query(query, &[&params.id, &account.id])?; .query(query, &[&params.id, &account.id])?;
@ -138,9 +136,7 @@ pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle
post_battle_plr = post_battle_plr.add_xp(); post_battle_plr = post_battle_plr.add_xp();
} }
cryp_write(post_battle_plr, &mut tx)?; cryp_write(post_battle_plr, tx)?;
tx.commit()?;
break Ok(battle) break Ok(battle)
} }

View File

@ -214,7 +214,7 @@ pub fn cryp_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result<Cryp
return Ok(cryp); return Ok(cryp);
} }
pub fn cryp_spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result<Cryp, Error> { pub fn cryp_spawn(params: CrypSpawnParams, tx: &mut Transaction, account: &Account) -> Result<Cryp, Error> {
let cryp = Cryp::new() let cryp = Cryp::new()
.named(&params.name) .named(&params.name)
.level(1) .level(1)
@ -229,8 +229,6 @@ pub fn cryp_spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result
RETURNING id, account; RETURNING id, account;
"; ";
let tx = db.transaction()?;
let result = tx let result = tx
.query(query, &[&cryp.id, &account.id, &cryp_bytes])?; .query(query, &[&cryp.id, &account.id, &cryp_bytes])?;
@ -238,8 +236,6 @@ pub fn cryp_spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result
println!("{:?} spawned cryp {:}", account.id, cryp.id); println!("{:?} spawned cryp {:}", account.id, cryp.id);
tx.commit()?;
return Ok(cryp); return Ok(cryp);
} }

View File

@ -1,14 +1,14 @@
use account::Account;
use uuid::Uuid;
use serde_cbor::{from_slice, to_vec}; use serde_cbor::{from_slice, to_vec};
use uuid::Uuid;
use net::Db;
use postgres::transaction::Transaction; use postgres::transaction::Transaction;
use failure::Error;
use failure::err_msg;
use account::Account;
use rpc::{ItemUseParams}; use rpc::{ItemUseParams};
use cryp::{cryp_get, cryp_write}; use cryp::{cryp_get, cryp_write};
use failure::Error;
use failure::err_msg;
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum ItemAction { pub enum ItemAction {
@ -67,7 +67,7 @@ pub fn item_create(item: Item, tx: &mut Transaction, account: &Account) -> Resul
return Ok(item); return Ok(item);
} }
pub fn item_use(params: ItemUseParams, db: &Db, account: &Account) -> Result<(), Error> { pub fn item_use(params: ItemUseParams, tx: &mut Transaction, account: &Account) -> Result<(), Error> {
let query = " let query = "
SELECT data SELECT data
FOR UPDATE FOR UPDATE
@ -76,8 +76,6 @@ pub fn item_use(params: ItemUseParams, db: &Db, account: &Account) -> Result<(),
AND account = $2; AND account = $2;
"; ";
let mut tx = db.transaction()?;
let result = tx let result = tx
.query(query, &[&params.item, &account.id])?; .query(query, &[&params.item, &account.id])?;
@ -86,21 +84,19 @@ pub fn item_use(params: ItemUseParams, db: &Db, account: &Account) -> Result<(),
let item_bytes: Vec<u8> = returned.get(0); let item_bytes: Vec<u8> = returned.get(0);
let mut item = from_slice::<Item>(&item_bytes)?; let mut item = from_slice::<Item>(&item_bytes)?;
item.apply(&mut tx, params.target)?; item.apply(tx, params.target)?;
tx.commit()?;
return Ok(()); return Ok(());
} }
pub fn items_list(db: &Db, account: &Account) -> Result<Vec<Item>, Error> { pub fn items_list(tx: &mut Transaction, account: &Account) -> Result<Vec<Item>, Error> {
let query = " let query = "
SELECT data SELECT data
FROM items FROM items
WHERE account = $1; WHERE account = $1;
"; ";
let result = db let result = tx
.query(query, &[&account.id])?; .query(query, &[&account.id])?;
let items: Result<Vec<Item>, _> = result.iter().map(|row| { let items: Result<Vec<Item>, _> = result.iter().map(|row| {

View File

@ -1,6 +1,7 @@
use tungstenite::Message; use tungstenite::Message;
use tungstenite::protocol::WebSocket; use tungstenite::protocol::WebSocket;
use tungstenite::Message::Binary; use tungstenite::Message::Binary;
use postgres::transaction::Transaction;
use std::net::{TcpStream}; use std::net::{TcpStream};
use serde_cbor::{from_slice, to_vec}; use serde_cbor::{from_slice, to_vec};
@ -25,9 +26,10 @@ impl Rpc {
// cast the msg to this type to receive method name // cast the msg to this type to receive method name
match from_slice::<RpcMessage>(&data) { match from_slice::<RpcMessage>(&data) {
Ok(v) => { Ok(v) => {
let mut tx = db.transaction()?;
let account: Option<Account> = match v.token { let account: Option<Account> = match v.token {
Some(t) => Some(account_from_token(t, &db)?), Some(t) => Some(account_from_token(t, &mut tx)?),
None => None, None => None,
}; };
@ -35,17 +37,21 @@ impl Rpc {
// now we have the method name // now we have the method name
// match on that to determine what fn to call // match on that to determine what fn to call
match v.method.as_ref() { let response = match v.method.as_ref() {
"cryp_spawn" => Rpc::cryp_spawn(data, db, account), "cryp_spawn" => Rpc::cryp_spawn(data, &mut tx, account),
"combat_pve" => Rpc::combat_pve(data, db, account, client), "combat_pve" => Rpc::combat_pve(data, &mut tx, account, client),
"account_create" => Rpc::account_create(data, db), "account_create" => Rpc::account_create(data, &mut tx),
"account_login" => Rpc::account_login(data, db), "account_login" => Rpc::account_login(data, &mut tx),
"account_cryps" => Rpc::account_cryps(db, account), "account_cryps" => Rpc::account_cryps(&mut tx, account),
"item_list" => Rpc::item_list(db, account), "item_list" => Rpc::item_list(&mut tx, account),
"item_use" => Rpc::item_use(data, db, account), "item_use" => Rpc::item_use(data, &mut tx, account),
_ => Err(err_msg("unknown method")), _ => Err(err_msg("unknown method")),
} };
tx.commit()?;
return response;
}, },
Err(_e) => Err(err_msg("invalid message")), Err(_e) => Err(err_msg("invalid message")),
} }
@ -59,7 +65,7 @@ impl Rpc {
} }
} }
fn combat_pve(data: Vec<u8>, db: &Db, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> { fn combat_pve(data: Vec<u8>, tx: &mut Transaction, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account { let a = match account {
Some(a) => a, Some(a) => a,
None => return Err(err_msg("auth required")), None => return Err(err_msg("auth required")),
@ -69,24 +75,24 @@ impl Rpc {
let battle_response = RpcResponse { let battle_response = RpcResponse {
method: "battle_state".to_string(), method: "battle_state".to_string(),
params: RpcResult::Pve(pve(msg.params, db, &a)?) params: RpcResult::Pve(pve(msg.params, tx, &a)?)
}; };
Rpc::send_msg(client, RpcResponse { Rpc::send_msg(client, RpcResponse {
method: "account_cryps".to_string(), method: "account_cryps".to_string(),
params: RpcResult::CrypList(account_cryps(db, &a)?) params: RpcResult::CrypList(account_cryps(tx, &a)?)
})?; })?;
return Ok(battle_response); return Ok(battle_response);
} }
fn cryp_spawn(data: Vec<u8>, db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> { fn cryp_spawn(data: Vec<u8>, tx: &mut Transaction, account: Option<Account>) -> Result<RpcResponse, Error> {
match from_slice::<CrypSpawnMsg>(&data) { match from_slice::<CrypSpawnMsg>(&data) {
Ok(v) => { Ok(v) => {
match account { match account {
Some(a) => Ok(RpcResponse { Some(a) => Ok(RpcResponse {
method: v.method, method: v.method,
params: RpcResult::SpawnCryp(cryp_spawn(v.params, db, &a)?) params: RpcResult::SpawnCryp(cryp_spawn(v.params, tx, &a)?)
}), }),
None => Err(err_msg("auth required")), None => Err(err_msg("auth required")),
} }
@ -95,53 +101,53 @@ impl Rpc {
} }
} }
fn account_create(data: Vec<u8>, db: &Db) -> Result<RpcResponse, Error> { fn account_create(data: Vec<u8>, tx: &mut Transaction) -> Result<RpcResponse, Error> {
match from_slice::<AccountCreateMsg>(&data) { match from_slice::<AccountCreateMsg>(&data) {
Ok(v) => Ok(RpcResponse { Ok(v) => Ok(RpcResponse {
method: v.method, method: v.method,
params: RpcResult::Account(account_create(v.params, db)?) params: RpcResult::Account(account_create(v.params, tx)?)
}), }),
Err(_e) => Err(err_msg("invalid params")), Err(_e) => Err(err_msg("invalid params")),
} }
} }
fn account_login(data: Vec<u8>, db: &Db) -> Result<RpcResponse, Error> { fn account_login(data: Vec<u8>, tx: &mut Transaction) -> Result<RpcResponse, Error> {
match from_slice::<AccountLoginMsg>(&data) { match from_slice::<AccountLoginMsg>(&data) {
Ok(v) => Ok(RpcResponse { Ok(v) => Ok(RpcResponse {
method: v.method, method: v.method,
params: RpcResult::Account(account_login(v.params, db)?) params: RpcResult::Account(account_login(v.params, tx)?)
}), }),
Err(_e) => Err(err_msg("invalid params")), Err(_e) => Err(err_msg("invalid params")),
} }
} }
fn account_cryps(db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> { fn account_cryps(tx: &mut Transaction, account: Option<Account>) -> Result<RpcResponse, Error> {
match account { match account {
Some(a) => Ok(RpcResponse { Some(a) => Ok(RpcResponse {
method: "account_cryps".to_string(), method: "account_cryps".to_string(),
params: RpcResult::CrypList(account_cryps(db, &a)?) params: RpcResult::CrypList(account_cryps(tx, &a)?)
}), }),
None => Err(err_msg("auth required")), None => Err(err_msg("auth required")),
} }
} }
fn item_list(db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> { fn item_list(tx: &mut Transaction, account: Option<Account>) -> Result<RpcResponse, Error> {
match account { match account {
Some(a) => Ok(RpcResponse { Some(a) => Ok(RpcResponse {
method: "item_list".to_string(), method: "item_list".to_string(),
params: RpcResult::ItemList(items_list(db, &a)?) params: RpcResult::ItemList(items_list(tx, &a)?)
}), }),
None => Err(err_msg("auth required")), None => Err(err_msg("auth required")),
} }
} }
fn item_use(data: Vec<u8>, db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> { fn item_use(data: Vec<u8>, tx: &mut Transaction, account: Option<Account>) -> Result<RpcResponse, Error> {
match from_slice::<ItemUseMsg>(&data) { match from_slice::<ItemUseMsg>(&data) {
Ok(v) => { Ok(v) => {
match account { match account {
Some(a) => Ok(RpcResponse { Some(a) => Ok(RpcResponse {
method: v.method, method: v.method,
params: RpcResult::ItemUse(item_use(v.params, db, &a)?) params: RpcResult::ItemUse(item_use(v.params, tx, &a)?)
}), }),
None => Err(err_msg("auth required")), None => Err(err_msg("auth required")),
} }