Skip to content

Commit df415c0

Browse files
committed
GH-608: change the trait object to support SentPayables
1 parent 1534761 commit df415c0

File tree

1 file changed

+71
-54
lines changed

1 file changed

+71
-54
lines changed

node/src/accountant/db_access_objects/pending_payable_dao.rs

Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ use std::collections::HashSet;
1515
use std::fmt::Debug;
1616
use std::str::FromStr;
1717
use std::time::SystemTime;
18-
use web3::types::H256;
18+
use web3::types::{Address, H256};
19+
use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TxStatus;
1920

2021
#[derive(Debug, PartialEq, Eq)]
21-
pub enum PendingPayableDaoError {
22+
pub enum SentPayableDaoError {
2223
InsertionFailed(String),
2324
UpdateFailed(String),
2425
SignConversionError(u64),
@@ -28,27 +29,43 @@ pub enum PendingPayableDaoError {
2829
}
2930

3031
#[derive(Debug)]
31-
pub struct TransactionHashes {
32+
pub struct TxIdentifiers {
3233
pub rowid_results: Vec<(u64, H256)>,
3334
pub no_rowid_results: Vec<H256>,
3435
}
3536

36-
pub trait PendingPayableDao {
37+
struct TransactionRecord {
38+
tx: Tx,
39+
status: TxStatus,
40+
}
41+
42+
struct Tx {
43+
// GH-608: Perhaps TxReceipt could be a similar structure to be used
44+
receiver_address: Address,
45+
amount: u128,
46+
tx_hash: String,
47+
timestamp: SystemTime,
48+
gas_price_wei: u64,
49+
nonce: u32,
50+
}
51+
52+
struct StatusChange {
53+
new_status: TxStatus,
54+
}
55+
56+
pub trait SentPayableDao {
3757
// Note that the order of the returned results is not guaranteed
38-
fn fingerprints_rowids(&self, hashes: &[H256]) -> TransactionHashes;
39-
fn return_all_errorless_fingerprints(&self) -> Vec<PendingPayableFingerprint>;
40-
fn insert_new_fingerprints(
41-
&self,
42-
hashes_and_amounts: &[HashAndAmount],
43-
batch_wide_timestamp: SystemTime,
44-
) -> Result<(), PendingPayableDaoError>;
45-
fn delete_fingerprints(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError>;
46-
fn increment_scan_attempts(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError>;
47-
fn mark_failures(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError>;
58+
fn get_tx_identifiers(&self, hashes: &[H256]) -> TxIdentifiers;
59+
fn retrieve_pending_txs(&self) -> Vec<Tx>;
60+
61+
fn retrieve_txs_to_retry(&self) -> Vec<Tx>;
62+
fn insert_new_records(&self, txs: Vec<Tx>) -> Result<(), SentPayableDaoError>;
63+
fn delete_records(&self, ids: &[u64]) -> Result<(), SentPayableDaoError>;
64+
fn change_statuses(&self, ids: &[StatusChange]) -> Result<(), SentPayableDaoError>;
4865
}
4966

50-
impl PendingPayableDao for PendingPayableDaoReal<'_> {
51-
fn fingerprints_rowids(&self, hashes: &[H256]) -> TransactionHashes {
67+
impl SentPayableDao for SentPayableDaoReal<'_> {
68+
fn transaction_rowids(&self, hashes: &[H256]) -> TxIdentifiers {
5269
//Vec<(Option<u64>, H256)> {
5370
fn hash_and_rowid_in_single_row(row: &Row) -> rusqlite::Result<(u64, H256)> {
5471
let hash_str: String = row.get(0).expectv("hash");
@@ -81,7 +98,7 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
8198
.cloned()
8299
.collect();
83100

84-
TransactionHashes {
101+
TxIdentifiers {
85102
rowid_results: all_found_records,
86103
no_rowid_results: hashes_of_missing_rowids,
87104
}
@@ -128,7 +145,7 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
128145
&self,
129146
hashes_and_amounts: &[HashAndAmount],
130147
batch_wide_timestamp: SystemTime,
131-
) -> Result<(), PendingPayableDaoError> {
148+
) -> Result<(), SentPayableDaoError> {
132149
fn values_clause_for_fingerprints_to_insert(
133150
hashes_and_amounts: &[HashAndAmount],
134151
batch_wide_timestamp: SystemTime,
@@ -162,11 +179,11 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
162179
hashes_and_amounts.len(),
163180
x
164181
),
165-
Err(e) => Err(PendingPayableDaoError::InsertionFailed(e.to_string())),
182+
Err(e) => Err(SentPayableDaoError::InsertionFailed(e.to_string())),
166183
}
167184
}
168185

169-
fn delete_fingerprints(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError> {
186+
fn delete_fingerprints(&self, ids: &[u64]) -> Result<(), SentPayableDaoError> {
170187
let sql = format!(
171188
"delete from pending_payable where rowid in ({})",
172189
Self::serialize_ids(ids)
@@ -183,11 +200,11 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
183200
ids.len(),
184201
num
185202
),
186-
Err(e) => Err(PendingPayableDaoError::RecordDeletion(e.to_string())),
203+
Err(e) => Err(SentPayableDaoError::RecordDeletion(e.to_string())),
187204
}
188205
}
189206

190-
fn increment_scan_attempts(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError> {
207+
fn increment_scan_attempts(&self, ids: &[u64]) -> Result<(), SentPayableDaoError> {
191208
let sql = format!(
192209
"update pending_payable set attempt = attempt + 1 where rowid in ({})",
193210
Self::serialize_ids(ids)
@@ -199,11 +216,11 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
199216
ids.len(),
200217
num
201218
),
202-
Err(e) => Err(PendingPayableDaoError::UpdateFailed(e.to_string())),
219+
Err(e) => Err(SentPayableDaoError::UpdateFailed(e.to_string())),
203220
}
204221
}
205222

206-
fn mark_failures(&self, ids: &[u64]) -> Result<(), PendingPayableDaoError> {
223+
fn mark_failures(&self, ids: &[u64]) -> Result<(), SentPayableDaoError> {
207224
let sql = format!(
208225
"update pending_payable set process_error = 'ERROR' where rowid in ({})",
209226
Self::serialize_ids(ids)
@@ -220,7 +237,7 @@ impl PendingPayableDao for PendingPayableDaoReal<'_> {
220237
ids.len(), num
221238
)
222239
,
223-
Err(e) => Err(PendingPayableDaoError::ErrorMarkFailed(e.to_string())),
240+
Err(e) => Err(SentPayableDaoError::ErrorMarkFailed(e.to_string())),
224241
}
225242
}
226243
}
@@ -241,11 +258,11 @@ impl PendingPayable {
241258
}
242259

243260
#[derive(Debug)]
244-
pub struct PendingPayableDaoReal<'a> {
261+
pub struct SentPayableDaoReal<'a> {
245262
conn: Box<dyn ConnectionWrapper + 'a>,
246263
}
247264

248-
impl<'a> PendingPayableDaoReal<'a> {
265+
impl<'a> SentPayableDaoReal<'a> {
249266
pub fn new(conn: Box<dyn ConnectionWrapper + 'a>) -> Self {
250267
Self { conn }
251268
}
@@ -260,20 +277,20 @@ impl<'a> PendingPayableDaoReal<'a> {
260277
}
261278

262279
pub trait PendingPayableDaoFactory {
263-
fn make(&self) -> Box<dyn PendingPayableDao>;
280+
fn make(&self) -> Box<dyn SentPayableDao>;
264281
}
265282

266283
impl PendingPayableDaoFactory for DaoFactoryReal {
267-
fn make(&self) -> Box<dyn PendingPayableDao> {
268-
Box::new(PendingPayableDaoReal::new(self.make_connection()))
284+
fn make(&self) -> Box<dyn SentPayableDao> {
285+
Box::new(SentPayableDaoReal::new(self.make_connection()))
269286
}
270287
}
271288

272289
#[cfg(test)]
273290
mod tests {
274291
use crate::accountant::checked_conversion;
275292
use crate::accountant::db_access_objects::pending_payable_dao::{
276-
PendingPayableDao, PendingPayableDaoError, PendingPayableDaoReal,
293+
SentPayableDao, SentPayableDaoError, SentPayableDaoReal,
277294
};
278295
use crate::accountant::db_access_objects::utils::from_time_t;
279296
use crate::accountant::db_big_integer::big_int_divider::BigIntDivider;
@@ -305,7 +322,7 @@ mod tests {
305322
let hash_2 = make_tx_hash(6789);
306323
let amount_2 = 44445;
307324
let batch_wide_timestamp = from_time_t(200_000_000);
308-
let subject = PendingPayableDaoReal::new(wrapped_conn);
325+
let subject = SentPayableDaoReal::new(wrapped_conn);
309326
let hash_and_amount_1 = HashAndAmount {
310327
hash: hash_1,
311328
amount: amount_1,
@@ -366,14 +383,14 @@ mod tests {
366383
let hash = make_tx_hash(45466);
367384
let amount = 55556;
368385
let timestamp = from_time_t(200_000_000);
369-
let subject = PendingPayableDaoReal::new(Box::new(wrapped_conn));
386+
let subject = SentPayableDaoReal::new(Box::new(wrapped_conn));
370387
let hash_and_amount = HashAndAmount { hash, amount };
371388

372389
let result = subject.insert_new_fingerprints(&[hash_and_amount], timestamp);
373390

374391
assert_eq!(
375392
result,
376-
Err(PendingPayableDaoError::InsertionFailed(
393+
Err(SentPayableDaoError::InsertionFailed(
377394
"attempt to write a readonly database".to_string()
378395
))
379396
)
@@ -395,7 +412,7 @@ mod tests {
395412
let hash_1 = make_tx_hash(4546);
396413
let amount_1 = 55556;
397414
let batch_wide_timestamp = from_time_t(200_000_000);
398-
let subject = PendingPayableDaoReal::new(Box::new(wrapped_conn));
415+
let subject = SentPayableDaoReal::new(Box::new(wrapped_conn));
399416
let hash_and_amount = HashAndAmount {
400417
hash: hash_1,
401418
amount: amount_1,
@@ -413,7 +430,7 @@ mod tests {
413430
let wrapped_conn = DbInitializerReal::default()
414431
.initialize(&home_dir, DbInitializationConfig::test_default())
415432
.unwrap();
416-
let subject = PendingPayableDaoReal::new(wrapped_conn);
433+
let subject = SentPayableDaoReal::new(wrapped_conn);
417434
let timestamp = from_time_t(195_000_000);
418435
// use full range tx hashes because SqLite has tendencies to see the value as a hex and convert it to an integer,
419436
// then complain about its excessive size if supplied in unquoted strings
@@ -438,7 +455,7 @@ mod tests {
438455
.unwrap();
439456
}
440457

441-
let result = subject.fingerprints_rowids(&[hash_1, hash_2]);
458+
let result = subject.transaction_rowids(&[hash_1, hash_2]);
442459

443460
let first_expected_pair = &(1, hash_1);
444461
assert!(
@@ -466,7 +483,7 @@ mod tests {
466483
let wrapped_conn = DbInitializerReal::default()
467484
.initialize(&home_dir, DbInitializationConfig::test_default())
468485
.unwrap();
469-
let subject = PendingPayableDaoReal::new(wrapped_conn);
486+
let subject = SentPayableDaoReal::new(wrapped_conn);
470487
let hash_1 = make_tx_hash(11119);
471488
let hash_2 = make_tx_hash(22229);
472489
let hash_3 = make_tx_hash(33339);
@@ -494,7 +511,7 @@ mod tests {
494511
.unwrap();
495512
subject.delete_fingerprints(&[1]).unwrap();
496513

497-
let result = subject.fingerprints_rowids(&[hash_1, hash_2, hash_3, hash_4]);
514+
let result = subject.transaction_rowids(&[hash_1, hash_2, hash_3, hash_4]);
498515

499516
assert_eq!(result.rowid_results, vec![(2, hash_3),]);
500517
assert_eq!(result.no_rowid_results, vec![hash_1, hash_2, hash_4]);
@@ -509,7 +526,7 @@ mod tests {
509526
let wrapped_conn = DbInitializerReal::default()
510527
.initialize(&home_dir, DbInitializationConfig::test_default())
511528
.unwrap();
512-
let subject = PendingPayableDaoReal::new(wrapped_conn);
529+
let subject = SentPayableDaoReal::new(wrapped_conn);
513530
let batch_wide_timestamp = from_time_t(195_000_000);
514531
let hash_1 = make_tx_hash(11119);
515532
let amount_1 = 787;
@@ -567,7 +584,7 @@ mod tests {
567584
let wrapped_conn = DbInitializerReal::default()
568585
.initialize(&home_dir, DbInitializationConfig::test_default())
569586
.unwrap();
570-
let subject = PendingPayableDaoReal::new(wrapped_conn);
587+
let subject = SentPayableDaoReal::new(wrapped_conn);
571588
let timestamp = from_time_t(198_000_000);
572589
let hash = make_tx_hash(10000);
573590
let amount = 333;
@@ -619,7 +636,7 @@ mod tests {
619636
.execute([])
620637
.unwrap();
621638
}
622-
let subject = PendingPayableDaoReal::new(wrapped_conn);
639+
let subject = SentPayableDaoReal::new(wrapped_conn);
623640

624641
let _ = subject.return_all_errorless_fingerprints();
625642
}
@@ -633,7 +650,7 @@ mod tests {
633650
let conn = DbInitializerReal::default()
634651
.initialize(&home_dir, DbInitializationConfig::test_default())
635652
.unwrap();
636-
let subject = PendingPayableDaoReal::new(conn);
653+
let subject = SentPayableDaoReal::new(conn);
637654
{
638655
subject
639656
.insert_new_fingerprints(
@@ -684,13 +701,13 @@ mod tests {
684701
.unwrap();
685702
let wrapped_conn = ConnectionWrapperReal::new(conn_read_only);
686703
let rowid = 45;
687-
let subject = PendingPayableDaoReal::new(Box::new(wrapped_conn));
704+
let subject = SentPayableDaoReal::new(Box::new(wrapped_conn));
688705

689706
let result = subject.delete_fingerprints(&[rowid]);
690707

691708
assert_eq!(
692709
result,
693-
Err(PendingPayableDaoError::RecordDeletion(
710+
Err(SentPayableDaoError::RecordDeletion(
694711
"attempt to write a readonly database".to_string()
695712
))
696713
)
@@ -710,7 +727,7 @@ mod tests {
710727
.unwrap();
711728
let rowid_1 = 1;
712729
let rowid_2 = 2;
713-
let subject = PendingPayableDaoReal::new(conn);
730+
let subject = SentPayableDaoReal::new(conn);
714731
{
715732
subject
716733
.insert_new_fingerprints(
@@ -751,7 +768,7 @@ mod tests {
751768
amount: 3344,
752769
};
753770
let timestamp = from_time_t(190_000_000);
754-
let subject = PendingPayableDaoReal::new(conn);
771+
let subject = SentPayableDaoReal::new(conn);
755772
{
756773
subject
757774
.insert_new_fingerprints(
@@ -794,13 +811,13 @@ mod tests {
794811
)
795812
.unwrap();
796813
let wrapped_conn = ConnectionWrapperReal::new(conn_read_only);
797-
let subject = PendingPayableDaoReal::new(Box::new(wrapped_conn));
814+
let subject = SentPayableDaoReal::new(Box::new(wrapped_conn));
798815

799816
let result = subject.increment_scan_attempts(&[1]);
800817

801818
assert_eq!(
802819
result,
803-
Err(PendingPayableDaoError::UpdateFailed(
820+
Err(SentPayableDaoError::UpdateFailed(
804821
"attempt to write a readonly database".to_string()
805822
))
806823
)
@@ -818,7 +835,7 @@ mod tests {
818835
let conn = DbInitializerReal::default()
819836
.initialize(&home_dir, DbInitializationConfig::test_default())
820837
.unwrap();
821-
let subject = PendingPayableDaoReal::new(conn);
838+
let subject = SentPayableDaoReal::new(conn);
822839

823840
let _ = subject.increment_scan_attempts(&[1, 2]);
824841
}
@@ -843,7 +860,7 @@ mod tests {
843860
amount: amount_2,
844861
};
845862
let timestamp = from_time_t(190_000_000);
846-
let subject = PendingPayableDaoReal::new(conn);
863+
let subject = SentPayableDaoReal::new(conn);
847864
{
848865
subject
849866
.insert_new_fingerprints(&[hash_and_amount_1, hash_and_amount_2], timestamp)
@@ -919,13 +936,13 @@ mod tests {
919936
)
920937
.unwrap();
921938
let wrapped_conn = ConnectionWrapperReal::new(conn_read_only);
922-
let subject = PendingPayableDaoReal::new(Box::new(wrapped_conn));
939+
let subject = SentPayableDaoReal::new(Box::new(wrapped_conn));
923940

924941
let result = subject.mark_failures(&[1]);
925942

926943
assert_eq!(
927944
result,
928-
Err(PendingPayableDaoError::ErrorMarkFailed(
945+
Err(SentPayableDaoError::ErrorMarkFailed(
929946
"attempt to write a readonly database".to_string()
930947
))
931948
)
@@ -943,7 +960,7 @@ mod tests {
943960
let conn = DbInitializerReal::default()
944961
.initialize(&home_dir, DbInitializationConfig::test_default())
945962
.unwrap();
946-
let subject = PendingPayableDaoReal::new(conn);
963+
let subject = SentPayableDaoReal::new(conn);
947964

948965
let _ = subject.mark_failures(&[10, 20]);
949966
}

0 commit comments

Comments
 (0)