From a3e88f936dce76d7977947603b352677921ecb5a Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 22:53:55 -0700 Subject: [PATCH 1/9] add async-trait rust crate --- crates/pg/Cargo.toml | 1 + crates/types/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/pg/Cargo.toml b/crates/pg/Cargo.toml index fced6bb1..00a951e5 100644 --- a/crates/pg/Cargo.toml +++ b/crates/pg/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" bb8 = "0.8.0" bb8-postgres = "0.8.1" tokio = "1.26.0" +async-trait = "0.1.73" tokio-postgres = {version = "0.7.7", features = ["with-chrono-0_4"]} types = { path = "../types" } sqls = { path = "../sqls" } \ No newline at end of file diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index de053c2f..a16efe24 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -13,3 +13,4 @@ serde_with = {version = "2.2.0", features = ["chrono_0_4"]} strum = {version = "0.24.1", features = ["derive"]} strum_macros = "0.24.3" tokio-postgres = {version = "0.7.7", features = ["with-chrono-0_4"]} +async-trait = "0.1.73" \ No newline at end of file From 1cd87fae10c579fa7f2c972b3e9ef9765a3849d8 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 22:54:08 -0700 Subject: [PATCH 2/9] cargo lockfile --- Cargo.lock | 55 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86e84f12..e771b3cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,13 +19,13 @@ checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.36", ] [[package]] @@ -235,7 +235,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.109", ] [[package]] @@ -252,7 +252,7 @@ checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -276,7 +276,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.109", ] [[package]] @@ -287,7 +287,7 @@ checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -346,7 +346,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -734,6 +734,7 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" name = "pg" version = "0.1.0" dependencies = [ + "async-trait", "bb8", "bb8-postgres", "sqls", @@ -777,7 +778,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -800,7 +801,7 @@ checksum = "9e76c801e97c9cf696097369e517785b98056e98b21149384c812febfc5912f2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -843,18 +844,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -981,7 +982,7 @@ checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1041,7 +1042,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1143,7 +1144,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.109", ] [[package]] @@ -1163,6 +1164,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e02e55d62894af2a08aca894c6577281f76769ba47c94d5756bec8ac6e7373" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -1269,7 +1281,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1378,7 +1390,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1436,6 +1448,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" name = "types" version = "0.1.0" dependencies = [ + "async-trait", "chrono", "postgres-protocol", "postgres-types", @@ -1529,7 +1542,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -1551,7 +1564,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] From ae305c5a05ed76c75085383a0166c429722e1bb0 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 22:56:26 -0700 Subject: [PATCH 3/9] add RuleInstanceStore trait --- crates/types/src/rule.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/types/src/rule.rs b/crates/types/src/rule.rs index 1dfe9d89..d3aa405f 100644 --- a/crates/types/src/rule.rs +++ b/crates/types/src/rule.rs @@ -5,6 +5,18 @@ use chrono::{DateTime, Utc}; use postgres_types::{FromSql, ToSql}; use serde::{Deserialize, Serialize}; use tokio_postgres::Row; +use async_trait::async_trait; + +#[async_trait] +pub trait RuleInstanceStore { + async fn get_profile_state_rule_instances(&self, account_role: AccountRole, state_name: String) -> RuleInstances; + async fn get_rule_instances_by_type_role_account(&self, account_role: AccountRole, account: String) -> RuleInstances; + async fn get_approval_rule_instances( + &self, + account_role: AccountRole, + account: String, + ) -> RuleInstances; +} #[derive(Eq, PartialEq, Debug, Deserialize, Serialize, FromSql, ToSql, Clone)] pub struct RuleInstance { From 16537865e94e669122e910ad7dea40dc9974bcf5 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 22:56:36 -0700 Subject: [PATCH 4/9] add AccountStore trait --- crates/types/src/account.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/types/src/account.rs b/crates/types/src/account.rs index 96c99963..65a75147 100644 --- a/crates/types/src/account.rs +++ b/crates/types/src/account.rs @@ -1,6 +1,17 @@ use postgres_types::{FromSql, ToSql}; use serde::Deserialize; use tokio_postgres::Row; +use async_trait::async_trait; +use std::error::Error; + +#[async_trait] +pub trait AccountStore { + async fn get_account_profiles( + &self, + accounts: Vec, + ) -> Result>; + async fn get_approvers_for_account(&self, account: String) -> Vec; +} #[derive(Eq, PartialEq, Debug, Deserialize, ToSql, FromSql, Clone)] pub struct AccountProfile { From 1401305b0e4c3a66fe4ea109f1d7c007588c5088 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 22:57:25 -0700 Subject: [PATCH 5/9] implement traits from type crate in postgres crate --- crates/pg/src/lib.rs | 87 +++++++++++--------------------------------- 1 file changed, 21 insertions(+), 66 deletions(-) diff --git a/crates/pg/src/lib.rs b/crates/pg/src/lib.rs index 0cb973d9..7c1e8d94 100644 --- a/crates/pg/src/lib.rs +++ b/crates/pg/src/lib.rs @@ -1,18 +1,18 @@ use std::env; - use bb8::{Pool, PooledConnection}; use bb8_postgres::PostgresConnectionManager; use sqls::{ - select_account_profile_by_account, select_account_profiles_by_db_cr_accounts, select_approvers, + select_account_profiles_by_db_cr_accounts, select_approvers, select_rule_instance_by_type_role_account, select_rule_instance_by_type_role_state, }; use std::error::Error; use tokio_postgres::{types::ToSql, NoTls}; use types::{ - account::{AccountProfile, AccountProfiles}, + account::{AccountProfiles, AccountStore}, account_role::AccountRole, - rule::RuleInstances, + rule::{RuleInstanceStore, RuleInstances}, }; +use async_trait::async_trait; pub struct DB; @@ -80,25 +80,9 @@ impl ConnectionPool { pub struct DatabaseConnection(PooledConnection<'static, PostgresConnectionManager>); -impl DatabaseConnection { - pub async fn get_account_profile( - &self, - account: String, - ) -> Result> { - let row = self - .0 - .query_one(select_account_profile_by_account().as_str(), &[&account]) - .await; - match row { - Err(row) => Err(Box::new(row)), - Ok(row) => { - let account_profile = AccountProfile::from_row(row); - Ok(account_profile) - } - } - } - - pub async fn get_account_profiles( +#[async_trait] +impl AccountStore for &DatabaseConnection { + async fn get_account_profiles( &self, accounts: Vec, ) -> Result> { @@ -125,23 +109,7 @@ impl DatabaseConnection { } } - pub async fn get_db_cr_account_profiles( - &self, - debitor: String, - creditor: String, - ) -> AccountProfiles { - let rows = self - .0 - .query( - select_account_profiles_by_db_cr_accounts().as_str(), - &[&debitor, &creditor], - ) - .await - .unwrap(); // todo: handle error - types::account::AccountProfiles::from_rows(rows) - } - - pub async fn get_approvers_for_account(&self, account: String) -> Vec { + async fn get_approvers_for_account(&self, account: String) -> Vec { let rows = self .0 .query(select_approvers().as_str(), &[&account]) @@ -150,56 +118,43 @@ impl DatabaseConnection { let account_approvers: Vec = rows.into_iter().map(|row| row.get(0)).collect(); account_approvers } +} - pub async fn get_approvers_for_accounts(&self, accounts: Vec) -> Vec { - let mut params: Vec<&(dyn ToSql + Sync)> = Vec::new(); - - for a in accounts.iter() { - params.push(a) - } - - let rows = self - .0 - .query(select_approvers().as_str(), ¶ms[..]) - .await - .unwrap(); // todo: handle error - let account_approvers: Vec = rows.into_iter().map(|row| row.get(0)).collect(); - account_approvers - } - - pub async fn get_approval_rule_instances( +#[async_trait] +impl RuleInstanceStore for &DatabaseConnection { + async fn get_profile_state_rule_instances( &self, account_role: AccountRole, - account: String, + state_name: String, ) -> RuleInstances { let rows = self .0 .query( - select_rule_instance_by_type_role_account().as_str(), - &[&"approval", &account_role, &account], + select_rule_instance_by_type_role_state().as_str(), + &[&"transaction_item", &account_role, &state_name], ) .await .unwrap(); // todo: handle error RuleInstances::from_rows(rows) } - pub async fn get_profile_state_rule_instances( + async fn get_rule_instances_by_type_role_account( &self, account_role: AccountRole, - state_name: String, + account: String, ) -> RuleInstances { let rows = self .0 .query( - select_rule_instance_by_type_role_state().as_str(), - &[&"transaction_item", &account_role, &state_name], + select_rule_instance_by_type_role_account().as_str(), + &[&"transaction_item", &account_role, &account], ) .await .unwrap(); // todo: handle error RuleInstances::from_rows(rows) } - pub async fn get_rule_instances_by_type_role_account( + async fn get_approval_rule_instances( &self, account_role: AccountRole, account: String, @@ -208,7 +163,7 @@ impl DatabaseConnection { .0 .query( select_rule_instance_by_type_role_account().as_str(), - &[&"transaction_item", &account_role, &account], + &[&"approval", &account_role, &account], ) .await .unwrap(); // todo: handle error From af16e168525d4619bf435436cc26fa3c3d8e1c4a Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 23:02:17 -0700 Subject: [PATCH 6/9] switch conn to generic and use new traits as bounds --- services/rule/src/main.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/services/rule/src/main.rs b/services/rule/src/main.rs index 51599465..0702acb6 100644 --- a/services/rule/src/main.rs +++ b/services/rule/src/main.rs @@ -4,24 +4,25 @@ use axum::{ routing::{get, post}, Router, }; -use pg::{ConnectionPool, DatabaseConnection, DB}; +use pg::{ConnectionPool, DB}; use rule::{create_response, expected_values, label_approved_transaction_items}; use std::{env, net::ToSocketAddrs}; use tokio::signal; use types::approval::{Approval, Approvals}; use types::{ + account::AccountStore, account_role::{RoleSequence, CREDITOR_FIRST, DEBITOR_FIRST}, request_response::IntraTransaction, + rule::RuleInstanceStore, time::TZTime, transaction_item::TransactionItems, }; - mod rules; const READINESS_CHECK_PATH: &str = "READINESS_CHECK_PATH"; -async fn apply_transaction_item_rules( - conn: &DatabaseConnection, +async fn apply_transaction_item_rules( + conn: C, role_sequence: RoleSequence, transaction_items: &TransactionItems, ) -> TransactionItems { @@ -103,8 +104,8 @@ async fn apply_transaction_item_rules( response } -async fn apply_approval_rules( - conn: &DatabaseConnection, +async fn apply_approval_rules( + conn: C, role_sequence: RoleSequence, transaction_items: &mut TransactionItems, approval_time: &TZTime, From 080cffa0fc35f4c9e5c95991fbe6215e3f8cfd64 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 23:07:10 -0700 Subject: [PATCH 7/9] rust lint --- crates/pg/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/pg/src/lib.rs b/crates/pg/src/lib.rs index 7c1e8d94..ae439e3f 100644 --- a/crates/pg/src/lib.rs +++ b/crates/pg/src/lib.rs @@ -1,18 +1,17 @@ -use std::env; +use async_trait::async_trait; use bb8::{Pool, PooledConnection}; use bb8_postgres::PostgresConnectionManager; use sqls::{ select_account_profiles_by_db_cr_accounts, select_approvers, select_rule_instance_by_type_role_account, select_rule_instance_by_type_role_state, }; -use std::error::Error; +use std::{env, error::Error}; use tokio_postgres::{types::ToSql, NoTls}; use types::{ account::{AccountProfiles, AccountStore}, account_role::AccountRole, rule::{RuleInstanceStore, RuleInstances}, }; -use async_trait::async_trait; pub struct DB; From 56556596d7b015ec43722165e9760acb46d37bd7 Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 23:11:27 -0700 Subject: [PATCH 8/9] add crates in rule workflow --- .github/workflows/dev-rule.yaml | 1 + crates/pg/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-rule.yaml b/.github/workflows/dev-rule.yaml index e5320b07..e317448b 100644 --- a/.github/workflows/dev-rule.yaml +++ b/.github/workflows/dev-rule.yaml @@ -4,6 +4,7 @@ on: push: paths: - 'services/rule/**' + - 'crates/**' branches-ignore: - 'master' diff --git a/crates/pg/src/lib.rs b/crates/pg/src/lib.rs index ae439e3f..00c9b0fb 100644 --- a/crates/pg/src/lib.rs +++ b/crates/pg/src/lib.rs @@ -39,7 +39,6 @@ impl DB { #[cfg(test)] mod tests { use super::*; - use std::env; #[test] From 656062a1034973320d82e8cf53a142ab9e13320e Mon Sep 17 00:00:00 2001 From: max funk Date: Sun, 17 Sep 2023 23:14:51 -0700 Subject: [PATCH 9/9] rust lint --- crates/types/src/account.rs | 4 ++-- crates/types/src/rule.rs | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/types/src/account.rs b/crates/types/src/account.rs index 65a75147..597fd1cd 100644 --- a/crates/types/src/account.rs +++ b/crates/types/src/account.rs @@ -1,8 +1,8 @@ +use async_trait::async_trait; use postgres_types::{FromSql, ToSql}; use serde::Deserialize; -use tokio_postgres::Row; -use async_trait::async_trait; use std::error::Error; +use tokio_postgres::Row; #[async_trait] pub trait AccountStore { diff --git a/crates/types/src/rule.rs b/crates/types/src/rule.rs index d3aa405f..3321eafa 100644 --- a/crates/types/src/rule.rs +++ b/crates/types/src/rule.rs @@ -1,16 +1,24 @@ use crate::account_role::AccountRole; use crate::time::TZTime; +use async_trait::async_trait; #[allow(unused_imports)] use chrono::{DateTime, Utc}; use postgres_types::{FromSql, ToSql}; use serde::{Deserialize, Serialize}; use tokio_postgres::Row; -use async_trait::async_trait; #[async_trait] pub trait RuleInstanceStore { - async fn get_profile_state_rule_instances(&self, account_role: AccountRole, state_name: String) -> RuleInstances; - async fn get_rule_instances_by_type_role_account(&self, account_role: AccountRole, account: String) -> RuleInstances; + async fn get_profile_state_rule_instances( + &self, + account_role: AccountRole, + state_name: String, + ) -> RuleInstances; + async fn get_rule_instances_by_type_role_account( + &self, + account_role: AccountRole, + account: String, + ) -> RuleInstances; async fn get_approval_rule_instances( &self, account_role: AccountRole,