@@ -185,8 +185,7 @@ pub struct ActivityParser {
185
185
#[ serde( with = "serializers::serde_node_id" ) ]
186
186
pub destination : NodeId ,
187
187
/// The time in the simulation to start the payment.
188
- #[ serde( default ) ]
189
- pub start_secs : u16 ,
188
+ pub start_secs : Option < u16 > ,
190
189
/// The number of payments to send over the course of the simulation.
191
190
#[ serde( default ) ]
192
191
pub count : Option < u64 > ,
@@ -207,7 +206,7 @@ pub struct ActivityDefinition {
207
206
/// The destination of the payment.
208
207
pub destination : NodeInfo ,
209
208
/// The time in the simulation to start the payment.
210
- pub start_secs : u16 ,
209
+ pub start_secs : Option < u16 > ,
211
210
/// The number of payments to send over the course of the simulation.
212
211
pub count : Option < u64 > ,
213
212
/// The interval of the event, as in every how many seconds the payment is performed.
@@ -328,7 +327,7 @@ pub struct PaymentGenerationError(String);
328
327
329
328
pub trait PaymentGenerator : Display + Send {
330
329
/// Returns the time that the payments should start
331
- fn payment_start ( & self ) -> Duration ;
330
+ fn payment_start ( & self ) -> Option < Duration > ;
332
331
333
332
/// Returns the number of payments that should be made
334
333
fn payment_count ( & self ) -> Option < u64 > ;
@@ -819,7 +818,9 @@ impl Simulation {
819
818
for description in self . activity . iter ( ) {
820
819
let activity_generator = DefinedPaymentActivity :: new (
821
820
description. destination . clone ( ) ,
822
- Duration :: from_secs ( description. start_secs . into ( ) ) ,
821
+ description
822
+ . start_secs
823
+ . map ( |start| Duration :: from_secs ( start. into ( ) ) ) ,
823
824
description. count ,
824
825
description. interval_secs ,
825
826
description. amount_msat ,
@@ -1087,22 +1088,7 @@ async fn produce_events<N: DestinationGenerator + ?Sized, A: PaymentGenerator +
1087
1088
}
1088
1089
}
1089
1090
1090
- let wait: Duration = if current_count == 0 {
1091
- let start = node_generator. payment_start ( ) ;
1092
- if start != Duration :: from_secs ( 0 ) {
1093
- log:: debug!(
1094
- "Using a start delay. The first payment for {source} will be at {:?}." ,
1095
- start
1096
- ) ;
1097
- }
1098
- start
1099
- } else {
1100
- let wait = node_generator
1101
- . next_payment_wait ( )
1102
- . map_err ( SimulationError :: PaymentGenerationError ) ?;
1103
- log:: debug!( "Next payment for {source} in {:?}." , wait) ;
1104
- wait
1105
- } ;
1091
+ let wait = get_payment_delay ( current_count, & source, node_generator. as_ref ( ) ) ?;
1106
1092
1107
1093
select ! {
1108
1094
biased;
@@ -1144,6 +1130,38 @@ async fn produce_events<N: DestinationGenerator + ?Sized, A: PaymentGenerator +
1144
1130
}
1145
1131
}
1146
1132
1133
+ /// Gets the wait time for the next payment. If this is the first payment being generated, and a specific start delay
1134
+ /// was set we return a once-off delay. Otherwise, the interval between payments is used.
1135
+ fn get_payment_delay < A : PaymentGenerator + ?Sized > (
1136
+ call_count : u64 ,
1137
+ source : & NodeInfo ,
1138
+ node_generator : & A ,
1139
+ ) -> Result < Duration , SimulationError > {
1140
+ // Note: we can't check if let Some() && call_count (syntax not allowed) so we add an additional branch in here.
1141
+ // The alternative is to call payment_start twice (which is _technically_ fine because it always returns the same
1142
+ // value), but this approach only costs us a few extra lines so we go for the more verbose approach so that we
1143
+ // don't have to make any assumptions about the underlying operation of payment_start.
1144
+ if call_count != 0 {
1145
+ let wait = node_generator
1146
+ . next_payment_wait ( )
1147
+ . map_err ( SimulationError :: PaymentGenerationError ) ?;
1148
+ log:: debug!( "Next payment for {source} in {:?}." , wait) ;
1149
+ Ok ( wait)
1150
+ } else if let Some ( start) = node_generator. payment_start ( ) {
1151
+ log:: debug!(
1152
+ "First payment for {source} will be after a start delay of {:?}." ,
1153
+ start
1154
+ ) ;
1155
+ Ok ( start)
1156
+ } else {
1157
+ let wait = node_generator
1158
+ . next_payment_wait ( )
1159
+ . map_err ( SimulationError :: PaymentGenerationError ) ?;
1160
+ log:: debug!( "First payment for {source} in {:?}." , wait) ;
1161
+ Ok ( wait)
1162
+ }
1163
+ }
1164
+
1147
1165
async fn consume_simulation_results (
1148
1166
logger : Arc < Mutex < PaymentResultLogger > > ,
1149
1167
mut receiver : Receiver < ( Payment , PaymentResult ) > ,
@@ -1380,7 +1398,10 @@ async fn track_payment_result(
1380
1398
1381
1399
#[ cfg( test) ]
1382
1400
mod tests {
1383
- use crate :: MutRng ;
1401
+ use crate :: { get_payment_delay, test_utils, MutRng , PaymentGenerationError , PaymentGenerator } ;
1402
+ use mockall:: mock;
1403
+ use std:: fmt;
1404
+ use std:: time:: Duration ;
1384
1405
1385
1406
#[ test]
1386
1407
fn create_seeded_mut_rng ( ) {
@@ -1407,4 +1428,74 @@ mod tests {
1407
1428
1408
1429
assert_ne ! ( rng_1. next_u64( ) , rng_2. next_u64( ) )
1409
1430
}
1431
+
1432
+ mock ! {
1433
+ pub Generator { }
1434
+
1435
+ impl fmt:: Display for Generator {
1436
+ fn fmt<' a>( & self , f: & mut fmt:: Formatter <' a>) -> fmt:: Result ;
1437
+ }
1438
+
1439
+ impl PaymentGenerator for Generator {
1440
+ fn payment_start( & self ) -> Option <Duration >;
1441
+ fn payment_count( & self ) -> Option <u64 >;
1442
+ fn next_payment_wait( & self ) -> Result <Duration , PaymentGenerationError >;
1443
+ fn payment_amount( & self , destination_capacity: Option <u64 >) -> Result <u64 , PaymentGenerationError >;
1444
+ }
1445
+ }
1446
+
1447
+ #[ test]
1448
+ fn test_no_payment_delay ( ) {
1449
+ let node = test_utils:: create_nodes ( 1 , 100_000 )
1450
+ . first ( )
1451
+ . unwrap ( )
1452
+ . 0
1453
+ . clone ( ) ;
1454
+
1455
+ // Setup mocked generator to have no start time and send payments every 5 seconds.
1456
+ let mut mock_generator = MockGenerator :: new ( ) ;
1457
+ mock_generator. expect_payment_start ( ) . return_once ( || None ) ;
1458
+ let payment_interval = Duration :: from_secs ( 5 ) ;
1459
+ mock_generator
1460
+ . expect_next_payment_wait ( )
1461
+ . returning ( move || Ok ( payment_interval) ) ;
1462
+
1463
+ assert_eq ! (
1464
+ get_payment_delay( 0 , & node, & mock_generator) . unwrap( ) ,
1465
+ payment_interval
1466
+ ) ;
1467
+ assert_eq ! (
1468
+ get_payment_delay( 1 , & node, & mock_generator) . unwrap( ) ,
1469
+ payment_interval
1470
+ ) ;
1471
+ }
1472
+
1473
+ #[ test]
1474
+ fn test_payment_delay ( ) {
1475
+ let node = test_utils:: create_nodes ( 1 , 100_000 )
1476
+ . first ( )
1477
+ . unwrap ( )
1478
+ . 0
1479
+ . clone ( ) ;
1480
+
1481
+ // Setup mocked generator to have a start delay and payment interval with different values.
1482
+ let mut mock_generator = MockGenerator :: new ( ) ;
1483
+ let start_delay = Duration :: from_secs ( 10 ) ;
1484
+ mock_generator
1485
+ . expect_payment_start ( )
1486
+ . return_once ( move || Some ( start_delay) ) ;
1487
+ let payment_interval = Duration :: from_secs ( 5 ) ;
1488
+ mock_generator
1489
+ . expect_next_payment_wait ( )
1490
+ . returning ( move || Ok ( payment_interval) ) ;
1491
+
1492
+ assert_eq ! (
1493
+ get_payment_delay( 0 , & node, & mock_generator) . unwrap( ) ,
1494
+ start_delay
1495
+ ) ;
1496
+ assert_eq ! (
1497
+ get_payment_delay( 1 , & node, & mock_generator) . unwrap( ) ,
1498
+ payment_interval
1499
+ ) ;
1500
+ }
1410
1501
}
0 commit comments