Implement the http variant of the bank server.
During that process, many shortcomings with the socket server and the bank lib were fixed. I am aware a massive commit like this is not ideal.
This commit is contained in:
parent
c69654a924
commit
dac95b7dae
34 changed files with 1797 additions and 140 deletions
78
bank/Cargo.lock
generated
78
bank/Cargo.lock
generated
|
@ -8,7 +8,7 @@ version = "0.7.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -23,20 +23,20 @@ version = "0.2.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bank-server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
"pretty_env_logger",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"anyhow",
|
||||
"log",
|
||||
"pretty_env_logger",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -51,11 +51,11 @@ version = "0.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -64,9 +64,9 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -75,7 +75,7 @@ version = "0.1.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -84,7 +84,7 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
dependencies = [
|
||||
"quick-error",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -99,7 +99,7 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -114,8 +114,8 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"env_logger",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -124,7 +124,7 @@ version = "1.0.36"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -139,7 +139,7 @@ version = "1.0.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -148,9 +148,9 @@ version = "1.5.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -165,9 +165,9 @@ version = "1.0.86"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -176,7 +176,7 @@ version = "1.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -185,7 +185,7 @@ version = "1.0.30"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -194,9 +194,9 @@ version = "1.0.30"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -211,7 +211,7 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -226,8 +226,8 @@ version = "0.3.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -242,7 +242,7 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::account::AccountError::{Inactive, InvalidAmount, Overdraw};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AccountError {
|
||||
#[error("can not overdraw account")]
|
||||
Overdraw(),
|
||||
Overdraw,
|
||||
#[error("account is inactive")]
|
||||
Inactive(),
|
||||
Inactive,
|
||||
#[error("amount must be > 0")]
|
||||
InvalidAmount(),
|
||||
InvalidAmount,
|
||||
#[error("account does not exist")]
|
||||
NotFound,
|
||||
#[error("account still has a balance")]
|
||||
AccountNotZero,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -52,33 +53,35 @@ impl Hash for Account {
|
|||
impl Account {
|
||||
#[cfg(test)]
|
||||
pub fn new() -> Self {
|
||||
Self { ..Default::default() }
|
||||
Self {
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deposit(&mut self, amount: f64) -> Result<()> {
|
||||
pub fn deposit(&mut self, amount: f64) -> Result<f64, AccountError> {
|
||||
self.check_account(amount)?;
|
||||
self.balance += amount;
|
||||
Ok(())
|
||||
Ok(self.balance)
|
||||
}
|
||||
|
||||
pub fn withdraw(&mut self, amount: f64) -> Result<()> {
|
||||
pub fn withdraw(&mut self, amount: f64) -> Result<f64, AccountError> {
|
||||
self.check_account(amount)?;
|
||||
|
||||
if self.balance - amount < 0 as f64 {
|
||||
bail!(Overdraw());
|
||||
return Err(AccountError::Overdraw);
|
||||
}
|
||||
self.balance -= amount;
|
||||
|
||||
Ok(())
|
||||
Ok(self.balance)
|
||||
}
|
||||
|
||||
fn check_account(&self, amount: f64) -> Result<()> {
|
||||
fn check_account(&self, amount: f64) -> Result<(), AccountError> {
|
||||
if !self.is_active {
|
||||
bail!(Inactive());
|
||||
return Err(AccountError::Inactive);
|
||||
}
|
||||
|
||||
if amount < 0 as f64 {
|
||||
bail!(InvalidAmount());
|
||||
return Err(AccountError::InvalidAmount);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,38 +1,61 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{RwLock, RwLockReadGuard};
|
||||
|
||||
#[cfg(test)]
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::account::Account;
|
||||
use crate::account::{Account, AccountError};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Bank {
|
||||
pub accounts: HashMap<String, RwLock<Account>>,
|
||||
}
|
||||
|
||||
impl Bank {
|
||||
pub fn new() -> Self {
|
||||
Self { accounts: HashMap::new() }
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn account_action<F: Fn(&mut Account) -> Result<f64, AccountError>>(
|
||||
bank: RwLockReadGuard<'_, Bank>,
|
||||
nr: &str,
|
||||
action: F,
|
||||
) -> Result<f64, AccountError> {
|
||||
match bank.accounts.get(nr) {
|
||||
None => Err(AccountError::NotFound),
|
||||
Some(account) => {
|
||||
let mut account = account.write().unwrap();
|
||||
action(&mut account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn account_numbers(&self) -> HashSet<String> {
|
||||
self.accounts.iter()
|
||||
self.accounts
|
||||
.iter()
|
||||
.filter(|(_, acc)| acc.read().unwrap().is_active)
|
||||
.map(|(_, acc)| acc.read().unwrap().number.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn create_account(&mut self, owner: String) -> String {
|
||||
let acc = Account { owner, ..Default::default() };
|
||||
let number = acc.number.clone();
|
||||
let acc = Account {
|
||||
owner,
|
||||
..Default::default()
|
||||
};
|
||||
let nr = acc.number.clone();
|
||||
|
||||
self.accounts.insert(acc.number.clone(), RwLock::new(acc));
|
||||
|
||||
number
|
||||
nr
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn transfer(&self, from: &mut Account, to: &mut Account, amount: f64) -> Result<()> {
|
||||
pub fn transfer(
|
||||
&self,
|
||||
from: &mut Account,
|
||||
to: &mut Account,
|
||||
amount: f64,
|
||||
) -> Result<(), AccountError> {
|
||||
from.withdraw(amount)?;
|
||||
to.deposit(amount)?;
|
||||
|
||||
|
@ -83,4 +106,4 @@ mod tests {
|
|||
|
||||
assert_eq!(1, bank.account_numbers().len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub mod account;
|
||||
pub mod bank;
|
||||
pub mod bank;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue