Skip to content

Commit 04515c5

Browse files
authored
GH-665: Introduce new states in FailedPayableDao (#666)
* GH-605: add the steps to solve this card * GH-605: change the recheck to status * GH-605: all tests pass in failed_payable_dao.rs * GH-605: few more changes * GH-605: add instructions inside test retry_payable_scanner_can_initiate_a_scan * GH-605: introduce mocks for FailedPayableDAO * GH-665: add another variant for the reason: General * GH-665: add the string conversion for General * GH-665: review changes
1 parent f565cb2 commit 04515c5

File tree

8 files changed

+350
-112
lines changed

8 files changed

+350
-112
lines changed

node/src/accountant/db_access_objects/failed_payable_dao.rs

Lines changed: 167 additions & 101 deletions
Large diffs are not rendered by default.

node/src/accountant/db_access_objects/test_utils.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rusqlite::{Connection, OpenFlags};
66
use crate::accountant::db_access_objects::sent_payable_dao::{ Tx};
77
use crate::accountant::db_access_objects::utils::{current_unix_timestamp, TxHash};
88
use web3::types::{Address};
9-
use crate::accountant::db_access_objects::failed_payable_dao::{FailedTx, FailureReason};
9+
use crate::accountant::db_access_objects::failed_payable_dao::{FailedTx, FailureReason, FailureStatus};
1010
use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TransactionBlock;
1111
use crate::database::db_initializer::{DbInitializationConfig, DbInitializer, DbInitializerReal, DATABASE_FILE};
1212
use crate::database::rusqlite_wrappers::ConnectionWrapperReal;
@@ -69,7 +69,7 @@ pub struct FailedTxBuilder {
6969
gas_price_wei_opt: Option<u128>,
7070
nonce_opt: Option<u64>,
7171
reason_opt: Option<FailureReason>,
72-
rechecked_opt: Option<bool>,
72+
status_opt: Option<FailureStatus>,
7373
}
7474

7575
impl FailedTxBuilder {
@@ -97,8 +97,8 @@ impl FailedTxBuilder {
9797
self
9898
}
9999

100-
pub fn rechecked(mut self, rechecked: bool) -> Self {
101-
self.rechecked_opt = Some(rechecked);
100+
pub fn status(mut self, failure_status: FailureStatus) -> Self {
101+
self.status_opt = Some(failure_status);
102102
self
103103
}
104104

@@ -113,7 +113,9 @@ impl FailedTxBuilder {
113113
reason: self
114114
.reason_opt
115115
.unwrap_or_else(|| FailureReason::PendingTooLong),
116-
rechecked: self.rechecked_opt.unwrap_or_else(|| false),
116+
status: self
117+
.status_opt
118+
.unwrap_or_else(|| FailureStatus::RetryRequired),
117119
}
118120
}
119121
}

node/src/accountant/scanners/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ impl StartableScanner<ScanForRetryPayables, QualifiedPayablesMessage> for Payabl
520520
_logger: &Logger,
521521
) -> Result<QualifiedPayablesMessage, StartScanError> {
522522
todo!("Complete me under GH-605")
523+
// 1. Find the failed payables
524+
// 2. Look into the payable DAO to update the amount
525+
// 3. Prepare UnpricedQualifiedPayables
523526
}
524527
}
525528

@@ -1737,6 +1740,17 @@ mod tests {
17371740

17381741
#[test]
17391742
fn retry_payable_scanner_can_initiate_a_scan() {
1743+
//
1744+
// Setup Part:
1745+
// DAOs: PayableDao, FailedPayableDao
1746+
// Fetch data from FailedPayableDao (inject it into Payable Scanner -- allow the change in production code).
1747+
// Scanners constructor will require to create it with the Factory -- try it
1748+
// Configure it such that it returns at least 2 failed tx
1749+
// Once I get those 2 records, I should get hold of those identifiers used in the Payable DAO
1750+
// Update the new balance for those transactions
1751+
// Modify Payable DAO and add another method, that will return just the corresponding payments
1752+
// The account which I get from the PayableDAO can go straight to the QualifiedPayableBeforePriceSelection
1753+
17401754
todo!("this must be set up under GH-605");
17411755
// TODO make sure the QualifiedPayableRawPack will express the difference from
17421756
// the NewPayable scanner: The QualifiedPayablesBeforeGasPriceSelection needs to carry

node/src/accountant/test_utils.rs

Lines changed: 158 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#![cfg(test)]
44

55
use crate::accountant::db_access_objects::banned_dao::{BannedDao, BannedDaoFactory};
6+
use crate::accountant::db_access_objects::failed_payable_dao::{
7+
FailedPayableDao, FailedPayableDaoError, FailedPayableDaoFactory, FailedTx,
8+
FailureRetrieveCondition, FailureStatus,
9+
};
610
use crate::accountant::db_access_objects::payable_dao::{
711
PayableAccount, PayableDao, PayableDaoError, PayableDaoFactory,
812
};
@@ -13,7 +17,7 @@ use crate::accountant::db_access_objects::receivable_dao::{
1317
ReceivableAccount, ReceivableDao, ReceivableDaoError, ReceivableDaoFactory,
1418
};
1519
use crate::accountant::db_access_objects::utils::{
16-
from_unix_timestamp, to_unix_timestamp, CustomQuery,
20+
from_unix_timestamp, to_unix_timestamp, CustomQuery, TxHash, TxIdentifiers,
1721
};
1822
use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster};
1923
use crate::accountant::scanners::payable_scanner_extension::msgs::{
@@ -45,6 +49,7 @@ use masq_lib::logger::Logger;
4549
use rusqlite::{Connection, OpenFlags, Row};
4650
use std::any::type_name;
4751
use std::cell::RefCell;
52+
use std::collections::{HashMap, HashSet};
4853
use std::fmt::Debug;
4954
use std::path::Path;
5055
use std::rc::Rc;
@@ -1077,6 +1082,158 @@ impl PendingPayableDaoFactoryMock {
10771082
}
10781083
}
10791084

1085+
#[derive(Default)]
1086+
pub struct FailedPayableDaoMock {
1087+
get_tx_identifiers_params: Arc<Mutex<Vec<HashSet<TxHash>>>>,
1088+
get_tx_identifiers_results: RefCell<Vec<TxIdentifiers>>,
1089+
insert_new_records_params: Arc<Mutex<Vec<Vec<FailedTx>>>>,
1090+
insert_new_records_results: RefCell<Vec<Result<(), FailedPayableDaoError>>>,
1091+
retrieve_txs_params: Arc<Mutex<Vec<Option<FailureRetrieveCondition>>>>,
1092+
retrieve_txs_results: RefCell<Vec<Vec<FailedTx>>>,
1093+
update_statuses_params: Arc<Mutex<Vec<HashMap<TxHash, FailureStatus>>>>,
1094+
update_statuses_results: RefCell<Vec<Result<(), FailedPayableDaoError>>>,
1095+
delete_records_params: Arc<Mutex<Vec<HashSet<TxHash>>>>,
1096+
delete_records_results: RefCell<Vec<Result<(), FailedPayableDaoError>>>,
1097+
}
1098+
1099+
impl FailedPayableDao for FailedPayableDaoMock {
1100+
fn get_tx_identifiers(&self, hashes: &HashSet<TxHash>) -> TxIdentifiers {
1101+
self.get_tx_identifiers_params
1102+
.lock()
1103+
.unwrap()
1104+
.push(hashes.clone());
1105+
self.get_tx_identifiers_results.borrow_mut().remove(0)
1106+
}
1107+
1108+
fn insert_new_records(&self, txs: &[FailedTx]) -> Result<(), FailedPayableDaoError> {
1109+
self.insert_new_records_params
1110+
.lock()
1111+
.unwrap()
1112+
.push(txs.to_vec());
1113+
self.insert_new_records_results.borrow_mut().remove(0)
1114+
}
1115+
1116+
fn retrieve_txs(&self, condition: Option<FailureRetrieveCondition>) -> Vec<FailedTx> {
1117+
self.retrieve_txs_params.lock().unwrap().push(condition);
1118+
self.retrieve_txs_results.borrow_mut().remove(0)
1119+
}
1120+
1121+
fn update_statuses(
1122+
&self,
1123+
status_updates: HashMap<TxHash, FailureStatus>,
1124+
) -> Result<(), FailedPayableDaoError> {
1125+
self.update_statuses_params
1126+
.lock()
1127+
.unwrap()
1128+
.push(status_updates);
1129+
self.update_statuses_results.borrow_mut().remove(0)
1130+
}
1131+
1132+
fn delete_records(&self, hashes: &HashSet<TxHash>) -> Result<(), FailedPayableDaoError> {
1133+
self.delete_records_params
1134+
.lock()
1135+
.unwrap()
1136+
.push(hashes.clone());
1137+
self.delete_records_results.borrow_mut().remove(0)
1138+
}
1139+
}
1140+
1141+
impl FailedPayableDaoMock {
1142+
pub fn new() -> Self {
1143+
Self::default()
1144+
}
1145+
1146+
pub fn get_tx_identifiers_params(mut self, params: &Arc<Mutex<Vec<HashSet<TxHash>>>>) -> Self {
1147+
self.get_tx_identifiers_params = params.clone();
1148+
self
1149+
}
1150+
1151+
pub fn get_tx_identifiers_result(self, result: TxIdentifiers) -> Self {
1152+
self.get_tx_identifiers_results.borrow_mut().push(result);
1153+
self
1154+
}
1155+
1156+
pub fn insert_new_records_params(mut self, params: &Arc<Mutex<Vec<Vec<FailedTx>>>>) -> Self {
1157+
self.insert_new_records_params = params.clone();
1158+
self
1159+
}
1160+
1161+
pub fn insert_new_records_result(self, result: Result<(), FailedPayableDaoError>) -> Self {
1162+
self.insert_new_records_results.borrow_mut().push(result);
1163+
self
1164+
}
1165+
1166+
pub fn retrieve_txs_params(
1167+
mut self,
1168+
params: &Arc<Mutex<Vec<Option<FailureRetrieveCondition>>>>,
1169+
) -> Self {
1170+
self.retrieve_txs_params = params.clone();
1171+
self
1172+
}
1173+
1174+
pub fn retrieve_txs_result(self, result: Vec<FailedTx>) -> Self {
1175+
self.retrieve_txs_results.borrow_mut().push(result);
1176+
self
1177+
}
1178+
1179+
pub fn update_statuses_params(
1180+
mut self,
1181+
params: &Arc<Mutex<Vec<HashMap<TxHash, FailureStatus>>>>,
1182+
) -> Self {
1183+
self.update_statuses_params = params.clone();
1184+
self
1185+
}
1186+
1187+
pub fn update_statuses_result(self, result: Result<(), FailedPayableDaoError>) -> Self {
1188+
self.update_statuses_results.borrow_mut().push(result);
1189+
self
1190+
}
1191+
1192+
pub fn delete_records_params(mut self, params: &Arc<Mutex<Vec<HashSet<TxHash>>>>) -> Self {
1193+
self.delete_records_params = params.clone();
1194+
self
1195+
}
1196+
1197+
pub fn delete_records_result(self, result: Result<(), FailedPayableDaoError>) -> Self {
1198+
self.delete_records_results.borrow_mut().push(result);
1199+
self
1200+
}
1201+
}
1202+
1203+
pub struct FailedPayableDaoFactoryMock {
1204+
make_params: Arc<Mutex<Vec<()>>>,
1205+
make_results: RefCell<Vec<Box<dyn FailedPayableDao>>>,
1206+
}
1207+
1208+
impl FailedPayableDaoFactory for FailedPayableDaoFactoryMock {
1209+
fn make(&self) -> Box<dyn FailedPayableDao> {
1210+
if self.make_results.borrow().len() == 0 {
1211+
panic!("FailedPayableDao Missing.")
1212+
};
1213+
self.make_params.lock().unwrap().push(());
1214+
self.make_results.borrow_mut().remove(0)
1215+
}
1216+
}
1217+
1218+
impl FailedPayableDaoFactoryMock {
1219+
pub fn new() -> Self {
1220+
Self {
1221+
make_params: Arc::new(Mutex::new(vec![])),
1222+
make_results: RefCell::new(vec![]),
1223+
}
1224+
}
1225+
1226+
pub fn make_params(mut self, params: &Arc<Mutex<Vec<()>>>) -> Self {
1227+
self.make_params = params.clone();
1228+
self
1229+
}
1230+
1231+
pub fn make_result(self, result: FailedPayableDaoMock) -> Self {
1232+
self.make_results.borrow_mut().push(Box::new(result));
1233+
self
1234+
}
1235+
}
1236+
10801237
pub struct PayableScannerBuilder {
10811238
payable_dao: PayableDaoMock,
10821239
pending_payable_dao: PendingPayableDaoMock,

node/src/database/db_initializer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl DbInitializerReal {
299299
gas_price_wei_low_b integer not null,
300300
nonce integer not null,
301301
reason text not null,
302-
rechecked integer not null
302+
status text not null
303303
)",
304304
[],
305305
)
@@ -846,7 +846,7 @@ mod tests {
846846
gas_price_wei_low_b,
847847
nonce,
848848
reason,
849-
rechecked
849+
status
850850
FROM failed_payable",
851851
)
852852
.unwrap();

node/src/database/db_migrations/migrations/migration_10_to_11.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl DatabaseMigration for Migrate_10_to_11 {
3434
gas_price_wei_low_b integer not null,
3535
nonce integer not null,
3636
reason text not null,
37-
rechecked integer not null
37+
status text not null
3838
)";
3939

4040
declaration_utils.execute_upon_transaction(&[

node/src/database/test_utils/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub const SQL_ATTRIBUTES_FOR_CREATING_FAILED_PAYABLE: &[&[&str]] = &[
3737
&["gas_price_wei_low_b", "integer", "not", "null"],
3838
&["nonce", "integer", "not", "null"],
3939
&["reason", "text", "not", "null"],
40-
&["rechecked", "integer", "not", "null"],
40+
&["status", "text", "not", "null"],
4141
];
4242

4343
#[derive(Debug, Default)]

node/src/hopper/routing_service.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,6 @@ mod tests {
529529
use masq_lib::test_utils::environment_guard::EnvironmentGuard;
530530
use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler};
531531
use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN;
532-
use std::fmt::format;
533532
use std::net::SocketAddr;
534533
use std::str::FromStr;
535534
use std::time::SystemTime;

0 commit comments

Comments
 (0)