@@ -185,8 +185,7 @@ pub struct ActivityParser {
185185 #[ serde( with = "serializers::serde_node_id" ) ]
186186 pub destination : NodeId ,
187187 /// The time in the simulation to start the payment.
188- #[ serde( default ) ]
189- pub start_secs : u16 ,
188+ pub start_secs : Option < u16 > ,
190189 /// The number of payments to send over the course of the simulation.
191190 #[ serde( default ) ]
192191 pub count : Option < u64 > ,
@@ -207,7 +206,7 @@ pub struct ActivityDefinition {
207206 /// The destination of the payment.
208207 pub destination : NodeInfo ,
209208 /// The time in the simulation to start the payment.
210- pub start_secs : u16 ,
209+ pub start_secs : Option < u16 > ,
211210 /// The number of payments to send over the course of the simulation.
212211 pub count : Option < u64 > ,
213212 /// The interval of the event, as in every how many seconds the payment is performed.
@@ -328,7 +327,7 @@ pub struct PaymentGenerationError(String);
328327
329328pub trait PaymentGenerator : Display + Send {
330329 /// Returns the time that the payments should start
331- fn payment_start ( & self ) -> Duration ;
330+ fn payment_start ( & self ) -> Option < Duration > ;
332331
333332 /// Returns the number of payments that should be made
334333 fn payment_count ( & self ) -> Option < u64 > ;
@@ -819,7 +818,9 @@ impl Simulation {
819818 for description in self . activity . iter ( ) {
820819 let activity_generator = DefinedPaymentActivity :: new (
821820 description. destination . clone ( ) ,
822- Duration :: from_secs ( description. start_secs . into ( ) ) ,
821+ description
822+ . start_secs
823+ . map ( |start| Duration :: from_secs ( start. into ( ) ) ) ,
823824 description. count ,
824825 description. interval_secs ,
825826 description. amount_msat ,
@@ -1087,22 +1088,7 @@ async fn produce_events<N: DestinationGenerator + ?Sized, A: PaymentGenerator +
10871088 }
10881089 }
10891090
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 ( ) ) ?;
11061092
11071093 select ! {
11081094 biased;
@@ -1144,6 +1130,38 @@ async fn produce_events<N: DestinationGenerator + ?Sized, A: PaymentGenerator +
11441130 }
11451131}
11461132
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+
11471165async fn consume_simulation_results (
11481166 logger : Arc < Mutex < PaymentResultLogger > > ,
11491167 mut receiver : Receiver < ( Payment , PaymentResult ) > ,
@@ -1380,7 +1398,10 @@ async fn track_payment_result(
13801398
13811399#[ cfg( test) ]
13821400mod 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 ;
13841405
13851406 #[ test]
13861407 fn create_seeded_mut_rng ( ) {
@@ -1407,4 +1428,74 @@ mod tests {
14071428
14081429 assert_ne ! ( rng_1. next_u64( ) , rng_2. next_u64( ) )
14091430 }
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+ }
14101501}
0 commit comments