Skip to content

Commit 06dd374

Browse files
authored
GH-598: Receivables scheduling hot fix (#750)
1 parent 1ba4317 commit 06dd374

File tree

7 files changed

+472
-329
lines changed

7 files changed

+472
-329
lines changed

node/src/accountant/mod.rs

Lines changed: 193 additions & 183 deletions
Large diffs are not rendered by default.

node/src/accountant/scanners/mod.rs

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ impl Scanners {
122122
});
123123
}
124124

125-
Self::start_correct_payable_scanner::<ScanForNewPayables>(
125+
<(dyn MultistageDualPayableScanner) as StartableScanner<
126+
ScanForNewPayables,
127+
InitialTemplatesMessage,
128+
>>::start_scan(
126129
&mut *self.payable,
127130
wallet,
128131
timestamp,
@@ -150,7 +153,10 @@ impl Scanners {
150153
)
151154
}
152155

153-
Self::start_correct_payable_scanner::<ScanForRetryPayables>(
156+
<(dyn MultistageDualPayableScanner) as StartableScanner<
157+
ScanForRetryPayables,
158+
InitialTemplatesMessage,
159+
>>::start_scan(
154160
&mut *self.payable,
155161
wallet,
156162
timestamp,
@@ -168,10 +174,14 @@ impl Scanners {
168174
automatic_scans_enabled: bool,
169175
) -> Result<RequestTransactionReceipts, StartScanError> {
170176
let triggered_manually = response_skeleton_opt.is_some();
171-
self.check_general_conditions_for_pending_payable_scan(
172-
triggered_manually,
173-
automatic_scans_enabled,
174-
)?;
177+
if triggered_manually && automatic_scans_enabled {
178+
return Err(StartScanError::ManualTriggerError(
179+
ManulTriggerError::AutomaticScanConflict,
180+
));
181+
}
182+
183+
self.check_pending_payable_existence(triggered_manually)?;
184+
175185
match (
176186
self.pending_payable.scan_started_at(),
177187
self.payable.scan_started_at(),
@@ -299,41 +309,14 @@ impl Scanners {
299309
self.initial_pending_payable_scan = false
300310
}
301311

302-
// This is a helper function reducing a boilerplate of complex trait resolving where
303-
// the compiler requires to specify which trigger message distinguishes the scan to run.
304-
// The payable scanner offers two modes through doubled implementations of StartableScanner
305-
// which uses the trigger message type as the only distinction between them.
306-
fn start_correct_payable_scanner<'a, TriggerMessage>(
307-
scanner: &'a mut (dyn MultistageDualPayableScanner + 'a),
308-
wallet: &Wallet,
309-
timestamp: SystemTime,
310-
response_skeleton_opt: Option<ResponseSkeleton>,
311-
logger: &Logger,
312-
) -> Result<InitialTemplatesMessage, StartScanError>
313-
where
314-
TriggerMessage: Message,
315-
(dyn MultistageDualPayableScanner + 'a):
316-
StartableScanner<TriggerMessage, InitialTemplatesMessage>,
317-
{
318-
<(dyn MultistageDualPayableScanner + 'a) as StartableScanner<
319-
TriggerMessage,
320-
InitialTemplatesMessage,
321-
>>::start_scan(scanner, wallet, timestamp, response_skeleton_opt, logger)
322-
}
323-
324-
fn check_general_conditions_for_pending_payable_scan(
312+
fn check_pending_payable_existence(
325313
&mut self,
326314
triggered_manually: bool,
327-
automatic_scans_enabled: bool,
328315
) -> Result<(), StartScanError> {
329-
if triggered_manually && automatic_scans_enabled {
330-
return Err(StartScanError::ManualTriggerError(
331-
ManulTriggerError::AutomaticScanConflict,
332-
));
333-
}
334316
if self.initial_pending_payable_scan {
335317
return Ok(());
336318
}
319+
337320
if triggered_manually && !self.aware_of_unresolved_pending_payable {
338321
return Err(StartScanError::ManualTriggerError(
339322
ManulTriggerError::UnnecessaryRequest {
@@ -1343,8 +1326,8 @@ mod tests {
13431326

13441327
#[test]
13451328
#[should_panic(
1346-
expected = "internal error: entered unreachable code: Automatic pending payable \
1347-
scan should never start if there are no pending payables to process."
1329+
expected = "internal error: entered unreachable code: Automatic pending payable scan should \
1330+
never start if there are no pending payables to process."
13481331
)]
13491332
fn pending_payable_scanner_bumps_into_zero_pending_payable_awareness_in_the_automatic_mode() {
13501333
let consuming_wallet = make_paying_wallet(b"consuming");
@@ -1363,11 +1346,12 @@ mod tests {
13631346
}
13641347

13651348
#[test]
1366-
fn check_general_conditions_for_pending_payable_scan_if_it_is_initial_pending_payable_scan() {
1349+
fn check_pending_payable_existence_for_initial_pending_payable_scan_and_zero_awareness() {
13671350
let mut subject = make_dull_subject();
1351+
subject.aware_of_unresolved_pending_payable = false;
13681352
subject.initial_pending_payable_scan = true;
13691353

1370-
let result = subject.check_general_conditions_for_pending_payable_scan(false, true);
1354+
let result = subject.check_pending_payable_existence(false);
13711355

13721356
assert_eq!(result, Ok(()));
13731357
assert_eq!(subject.initial_pending_payable_scan, true);

node/src/accountant/scanners/payable_scanner/start_scan.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl StartableScanner<ScanForNewPayables, InitialTemplatesMessage> for PayableSc
3535
match qualified_payables.is_empty() {
3636
true => {
3737
self.mark_as_ended(logger);
38-
Err(StartScanError::NothingToProcess)
38+
Err(StartScanError::nothing_to_process(response_skeleton_opt))
3939
}
4040
false => {
4141
info!(
@@ -89,7 +89,7 @@ mod tests {
8989
use crate::accountant::scanners::payable_scanner::tx_templates::initial::retry::{
9090
RetryTxTemplate, RetryTxTemplates,
9191
};
92-
use crate::accountant::scanners::Scanners;
92+
use crate::accountant::scanners::payable_scanner::MultistageDualPayableScanner;
9393
use crate::accountant::test_utils::{
9494
make_payable_account, FailedPayableDaoMock, PayableDaoMock,
9595
};
@@ -144,7 +144,10 @@ mod tests {
144144
.payable_dao(payable_dao)
145145
.build();
146146

147-
let result = Scanners::start_correct_payable_scanner::<ScanForRetryPayables>(
147+
let result = <(dyn MultistageDualPayableScanner) as StartableScanner<
148+
ScanForRetryPayables,
149+
InitialTemplatesMessage,
150+
>>::start_scan(
148151
&mut subject,
149152
&consuming_wallet,
150153
timestamp,

node/src/accountant/scanners/pending_payable_scanner/mod.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,12 @@ impl StartableScanner<ScanForPendingPayables, RequestTransactionReceipts>
9595

9696
info!(logger, "Scanning for pending payable");
9797

98-
let tx_hashes = self.harvest_tables(logger).map_err(|e| {
99-
self.mark_as_ended(logger);
100-
e
101-
})?;
98+
let tx_hashes = self
99+
.harvest_tables(logger, response_skeleton_opt)
100+
.map_err(|e| {
101+
self.mark_as_ended(logger);
102+
e
103+
})?;
102104

103105
Ok(RequestTransactionReceipts {
104106
tx_hashes,
@@ -162,7 +164,11 @@ impl PendingPayableScanner {
162164
}
163165
}
164166

165-
fn harvest_tables(&mut self, logger: &Logger) -> Result<Vec<TxHashByTable>, StartScanError> {
167+
fn harvest_tables(
168+
&mut self,
169+
logger: &Logger,
170+
response_skeleton_opt: Option<ResponseSkeleton>,
171+
) -> Result<Vec<TxHashByTable>, StartScanError> {
166172
debug!(logger, "Harvesting sent_payable and failed_payable tables");
167173

168174
let pending_tx_hashes_opt = self.harvest_pending_payables();
@@ -172,7 +178,7 @@ impl PendingPayableScanner {
172178
pending_tx_hashes_opt.as_ref(),
173179
failure_hashes_opt.as_ref(),
174180
) {
175-
return Err(StartScanError::NothingToProcess);
181+
return Err(StartScanError::nothing_to_process(response_skeleton_opt));
176182
}
177183

178184
Self::log_records_for_receipt_check(
@@ -878,7 +884,9 @@ mod tests {
878884
};
879885
use crate::accountant::scanners::pending_payable_scanner::PendingPayableScanner;
880886
use crate::accountant::scanners::test_utils::PendingPayableCacheMock;
881-
use crate::accountant::scanners::{Scanner, StartScanError, StartableScanner};
887+
use crate::accountant::scanners::{
888+
AutomaticError, CommonError, Scanner, StartScanError, StartableScanner,
889+
};
882890
use crate::accountant::test_utils::{
883891
make_transaction_block, FailedPayableDaoMock, PayableDaoMock, PendingPayableScannerBuilder,
884892
SentPayableDaoMock,
@@ -1230,7 +1238,12 @@ mod tests {
12301238
let result = subject.start_scan(&consuming_wallet, now, None, &Logger::new("test"));
12311239

12321240
let is_scan_running = subject.scan_started_at().is_some();
1233-
assert_eq!(result, Err(StartScanError::NothingToProcess));
1241+
assert_eq!(
1242+
result,
1243+
Err(StartScanError::Automatic(AutomaticError::Common(
1244+
CommonError::NothingToProcess
1245+
)))
1246+
);
12341247
assert_eq!(is_scan_running, false);
12351248
}
12361249

0 commit comments

Comments
 (0)