@@ -70,6 +70,7 @@ impl TriggerCondition {
70
70
freq_in_secs : bool ,
71
71
timezone_offset : i32 ,
72
72
apply_silence : bool ,
73
+ start_from : Option < i64 > ,
73
74
) -> Result < i64 , anyhow:: Error > {
74
75
let frequency = if freq_in_secs {
75
76
self . frequency
@@ -84,11 +85,16 @@ impl TriggerCondition {
84
85
}
85
86
_ => 0 ,
86
87
} ;
88
+ let start_utc = start_from. map_or ( Ok ( Utc :: now ( ) ) , |from| {
89
+ chrono:: DateTime :: < Utc > :: from_timestamp_micros ( from) . ok_or ( anyhow:: anyhow!(
90
+ "Error converting start_from value to timestamp"
91
+ ) )
92
+ } ) ?;
87
93
let timezone_offset = FixedOffset :: east_opt ( timezone_offset * 60 ) . unwrap ( ) ;
88
94
if self . frequency_type == FrequencyType :: Cron {
89
95
let schedule = Schedule :: from_str ( & self . cron ) ?;
90
96
if apply_silence {
91
- let silence = Utc :: now ( ) + Duration :: try_minutes ( self . silence ) . unwrap ( ) ;
97
+ let silence = start_utc + Duration :: try_minutes ( self . silence ) . unwrap ( ) ;
92
98
let silence = silence. with_timezone ( & timezone_offset) ;
93
99
// Check for the cron timestamp after the silence period
94
100
Ok ( schedule. after ( & silence) . next ( ) . unwrap ( ) . timestamp_micros ( ) + tolerance)
@@ -110,14 +116,14 @@ impl TriggerCondition {
110
116
// should use the max of (frequency, silence) as the next_run_at.
111
117
// Silence period is in minutes, and the frequency is in seconds.
112
118
let delta = std:: cmp:: max ( frequency, self . silence * 60 ) ;
113
- Ok ( Utc :: now ( ) . timestamp_micros ( )
119
+ Ok ( start_utc . timestamp_micros ( )
114
120
+ Duration :: try_seconds ( delta)
115
121
. unwrap ( )
116
122
. num_microseconds ( )
117
123
. unwrap ( )
118
124
+ tolerance)
119
125
} else {
120
- Ok ( Utc :: now ( ) . timestamp_micros ( )
126
+ Ok ( start_utc . timestamp_micros ( )
121
127
+ Duration :: try_seconds ( frequency)
122
128
. unwrap ( )
123
129
. num_microseconds ( )
@@ -183,9 +189,14 @@ impl TriggerCondition {
183
189
freq_in_secs : bool ,
184
190
timezone_offset : i32 ,
185
191
apply_silence : bool ,
192
+ start_from : Option < i64 > ,
186
193
) -> Result < i64 , anyhow:: Error > {
187
- let next_run_at =
188
- self . get_next_trigger_time_non_aligned ( freq_in_secs, timezone_offset, apply_silence) ?;
194
+ let next_run_at = self . get_next_trigger_time_non_aligned (
195
+ freq_in_secs,
196
+ timezone_offset,
197
+ apply_silence,
198
+ start_from,
199
+ ) ?;
189
200
// Cron frequency is handled by the cron library, so we don't need to align it
190
201
if self . frequency_type != FrequencyType :: Cron {
191
202
// `align_time` expects frequency in seconds, so convert if necessary
@@ -205,11 +216,22 @@ impl TriggerCondition {
205
216
freq_in_secs : bool ,
206
217
timezone_offset : i32 ,
207
218
apply_silence : bool ,
219
+ start_from : Option < i64 > ,
208
220
) -> Result < i64 , anyhow:: Error > {
209
221
if self . align_time {
210
- self . get_aligned_next_trigger_time ( freq_in_secs, timezone_offset, apply_silence)
222
+ self . get_aligned_next_trigger_time (
223
+ freq_in_secs,
224
+ timezone_offset,
225
+ apply_silence,
226
+ start_from,
227
+ )
211
228
} else {
212
- self . get_next_trigger_time_non_aligned ( freq_in_secs, timezone_offset, apply_silence)
229
+ self . get_next_trigger_time_non_aligned (
230
+ freq_in_secs,
231
+ timezone_offset,
232
+ apply_silence,
233
+ start_from,
234
+ )
213
235
}
214
236
}
215
237
}
@@ -595,7 +617,7 @@ mod test {
595
617
..Default :: default ( )
596
618
} ;
597
619
let result = condition
598
- . get_next_trigger_time_non_aligned ( true , 0 , false )
620
+ . get_next_trigger_time_non_aligned ( true , 0 , false , None )
599
621
. unwrap ( ) ;
600
622
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
601
623
let after_5_minutes = Utc :: now ( ) + Duration :: minutes ( 5 ) ;
@@ -609,7 +631,7 @@ mod test {
609
631
..Default :: default ( )
610
632
} ;
611
633
let result = condition
612
- . get_next_trigger_time_non_aligned ( true , 0 , false )
634
+ . get_next_trigger_time_non_aligned ( true , 0 , false , None )
613
635
. unwrap ( ) ;
614
636
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
615
637
assert_eq ! ( dt. minute( ) % 5 , 0 ) ;
@@ -622,7 +644,7 @@ mod test {
622
644
..Default :: default ( )
623
645
} ;
624
646
let result = condition
625
- . get_next_trigger_time_non_aligned ( true , 0 , true )
647
+ . get_next_trigger_time_non_aligned ( true , 0 , true , None )
626
648
. unwrap ( ) ;
627
649
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
628
650
// The next trigger should be after the silence period
@@ -637,7 +659,7 @@ mod test {
637
659
..Default :: default ( )
638
660
} ;
639
661
let result = condition
640
- . get_next_trigger_time_non_aligned ( true , 0 , false )
662
+ . get_next_trigger_time_non_aligned ( true , 0 , false , None )
641
663
. unwrap ( ) ;
642
664
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
643
665
// The next trigger should be within the tolerance range
@@ -659,7 +681,7 @@ mod test {
659
681
660
682
// Mock the current time for testing
661
683
let result = condition
662
- . get_aligned_next_trigger_time ( true , 0 , false )
684
+ . get_aligned_next_trigger_time ( true , 0 , false , None )
663
685
. unwrap ( ) ;
664
686
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
665
687
@@ -682,7 +704,7 @@ mod test {
682
704
// For cron expressions, the time should not be aligned by our function
683
705
// as it's handled by the cron library
684
706
let result = condition
685
- . get_aligned_next_trigger_time ( true , 0 , false )
707
+ . get_aligned_next_trigger_time ( true , 0 , false , None )
686
708
. unwrap ( ) ;
687
709
let dt = DateTime :: from_timestamp_micros ( result) . unwrap ( ) ;
688
710
0 commit comments