@@ -83,7 +83,8 @@ impl BuildQueue {
83
83
ON CONFLICT (name, version) DO UPDATE
84
84
SET priority = EXCLUDED.priority,
85
85
registry = EXCLUDED.registry,
86
- attempt = 0
86
+ attempt = 0,
87
+ last_attempt = NULL
87
88
;" ,
88
89
& [ & name, & version, & priority, & registry] ,
89
90
) ?;
@@ -179,11 +180,16 @@ impl BuildQueue {
179
180
. query_opt (
180
181
"SELECT id, name, version, priority, registry
181
182
FROM queue
182
- WHERE attempt < $1
183
+ WHERE
184
+ attempt < $1 AND
185
+ (last_attempt IS NULL OR last_attempt < NOW() - make_interval(secs => $2))
183
186
ORDER BY priority ASC, attempt ASC, id ASC
184
187
LIMIT 1
185
188
FOR UPDATE SKIP LOCKED" ,
186
- & [ & self . max_attempts ] ,
189
+ & [
190
+ & self . max_attempts ,
191
+ & self . config . delay_between_build_attempts . as_secs_f64 ( ) ,
192
+ ] ,
187
193
) ?
188
194
. map ( |row| QueuedCrate {
189
195
id : row. get ( "id" ) ,
@@ -219,7 +225,12 @@ impl BuildQueue {
219
225
// Increase attempt count
220
226
let attempt: i32 = transaction
221
227
. query_one (
222
- "UPDATE queue SET attempt = attempt + 1 WHERE id = $1 RETURNING attempt;" ,
228
+ "UPDATE queue
229
+ SET
230
+ attempt = attempt + 1,
231
+ last_attempt = NOW()
232
+ WHERE id = $1
233
+ RETURNING attempt;" ,
223
234
& [ & to_process. id ] ,
224
235
) ?
225
236
. get ( 0 ) ;
@@ -502,6 +513,8 @@ impl BuildQueue {
502
513
#[ cfg( test) ]
503
514
mod tests {
504
515
use super :: * ;
516
+ use chrono:: { DateTime , Utc } ;
517
+ use std:: time:: Duration ;
505
518
506
519
#[ test]
507
520
fn test_add_duplicate_doesnt_fail_last_priority_wins ( ) {
@@ -531,8 +544,8 @@ mod tests {
531
544
let mut conn = env. db ( ) . conn ( ) ;
532
545
conn. execute (
533
546
"
534
- INSERT INTO queue (name, version, priority, attempt )
535
- VALUES ('failed_crate', '0.1.1', 0, 99)" ,
547
+ INSERT INTO queue (name, version, priority, attempt, last_attempt )
548
+ VALUES ('failed_crate', '0.1.1', 0, 99, NOW() )" ,
536
549
& [ ] ,
537
550
) ?;
538
551
@@ -544,14 +557,15 @@ mod tests {
544
557
545
558
let row = conn
546
559
. query_opt (
547
- "SELECT priority, attempt
560
+ "SELECT priority, attempt, last_attempt
548
561
FROM queue
549
562
WHERE name = $1 AND version = $2" ,
550
563
& [ & "failed_crate" , & "0.1.1" ] ,
551
564
) ?
552
565
. unwrap ( ) ;
553
566
assert_eq ! ( row. get:: <_, i32 >( 0 ) , 9 ) ;
554
567
assert_eq ! ( row. get:: <_, i32 >( 1 ) , 0 ) ;
568
+ assert ! ( row. get:: <_, Option <DateTime <Utc >>>( 2 ) . is_none( ) ) ;
555
569
Ok ( ( ) )
556
570
} )
557
571
}
@@ -574,13 +588,60 @@ mod tests {
574
588
} )
575
589
}
576
590
591
+ #[ test]
592
+ fn test_wait_between_build_attempts ( ) {
593
+ crate :: test:: wrapper ( |env| {
594
+ env. override_config ( |config| {
595
+ config. build_attempts = 99 ;
596
+ config. delay_between_build_attempts = Duration :: from_secs ( 1 ) ;
597
+ } ) ;
598
+
599
+ let queue = env. build_queue ( ) ;
600
+
601
+ queue. add_crate ( "krate" , "1.0.0" , 0 , None ) ?;
602
+
603
+ // first let it fail
604
+ queue. process_next_crate ( |krate| {
605
+ assert_eq ! ( krate. name, "krate" ) ;
606
+ anyhow:: bail!( "simulate a failure" ) ;
607
+ } ) ?;
608
+
609
+ queue. process_next_crate ( |_| {
610
+ // this can't happen since we didn't wait between attempts
611
+ unreachable ! ( ) ;
612
+ } ) ?;
613
+
614
+ {
615
+ // fake the build-attempt timestamp so it's older
616
+ let mut conn = env. db ( ) . conn ( ) ;
617
+ conn. execute (
618
+ "UPDATE queue SET last_attempt = $1" ,
619
+ & [ & ( Utc :: now ( ) - chrono:: Duration :: seconds ( 60 ) ) ] ,
620
+ ) ?;
621
+ }
622
+
623
+ let mut handled = false ;
624
+ // now we can process it again
625
+ queue. process_next_crate ( |krate| {
626
+ assert_eq ! ( krate. name, "krate" ) ;
627
+ handled = true ;
628
+ Ok ( ( ) )
629
+ } ) ?;
630
+
631
+ assert ! ( handled) ;
632
+
633
+ Ok ( ( ) )
634
+ } )
635
+ }
636
+
577
637
#[ test]
578
638
fn test_add_and_process_crates ( ) {
579
639
const MAX_ATTEMPTS : u16 = 3 ;
580
640
581
641
crate :: test:: wrapper ( |env| {
582
642
env. override_config ( |config| {
583
643
config. build_attempts = MAX_ATTEMPTS ;
644
+ config. delay_between_build_attempts = Duration :: ZERO ;
584
645
} ) ;
585
646
586
647
let queue = env. build_queue ( ) ;
@@ -775,6 +836,7 @@ mod tests {
775
836
crate :: test:: wrapper ( |env| {
776
837
env. override_config ( |config| {
777
838
config. build_attempts = MAX_ATTEMPTS ;
839
+ config. delay_between_build_attempts = Duration :: ZERO ;
778
840
} ) ;
779
841
let queue = env. build_queue ( ) ;
780
842
0 commit comments