Skip to content

Commit e6b202a

Browse files
committed
fix build re-attempts after pre-build error
1 parent d83f06a commit e6b202a

File tree

4 files changed

+196
-63
lines changed

4 files changed

+196
-63
lines changed

src/build_queue.rs

+88-37
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use crate::cdn;
21
use crate::db::{delete_crate, delete_version, update_latest_version_id, Pool};
32
use crate::docbuilder::PackageKind;
43
use crate::error::Result;
54
use crate::storage::Storage;
65
use crate::utils::{get_config, get_crate_priority, report_error, retry, set_config, ConfigName};
76
use crate::Context;
7+
use crate::{cdn, BuildPackageSummary};
88
use crate::{Config, Index, InstanceMetrics, RustwideBuilder};
99
use anyhow::Context as _;
1010
use fn_error_context::context;
@@ -168,7 +168,10 @@ impl BuildQueue {
168168
.is_some())
169169
}
170170

171-
fn process_next_crate(&self, f: impl FnOnce(&QueuedCrate) -> Result<()>) -> Result<()> {
171+
fn process_next_crate(
172+
&self,
173+
f: impl FnOnce(&QueuedCrate) -> Result<BuildPackageSummary>,
174+
) -> Result<()> {
172175
let mut conn = self.db.get()?;
173176
let mut transaction = conn.transaction()?;
174177

@@ -204,44 +207,56 @@ impl BuildQueue {
204207
None => return Ok(()),
205208
};
206209

207-
let res = self.metrics.build_time.observe_closure_duration(|| {
208-
f(&to_process).with_context(|| {
209-
format!(
210-
"Failed to build package {}-{} from queue",
211-
to_process.name, to_process.version
212-
)
213-
})
214-
});
210+
let res = self
211+
.metrics
212+
.build_time
213+
.observe_closure_duration(|| f(&to_process));
214+
215215
self.metrics.total_builds.inc();
216216
if let Err(err) =
217217
cdn::queue_crate_invalidation(&mut transaction, &self.config, &to_process.name)
218218
{
219219
report_error(&err);
220220
}
221221

222-
match res {
223-
Ok(()) => {
224-
transaction.execute("DELETE FROM queue WHERE id = $1;", &[&to_process.id])?;
225-
}
226-
Err(e) => {
227-
// Increase attempt count
228-
let attempt: i32 = transaction
229-
.query_one(
230-
"UPDATE queue
222+
let mut increase_attempt_count = || -> Result<()> {
223+
let attempt: i32 = transaction
224+
.query_one(
225+
"UPDATE queue
231226
SET
232227
attempt = attempt + 1,
233228
last_attempt = NOW()
234229
WHERE id = $1
235230
RETURNING attempt;",
236-
&[&to_process.id],
237-
)?
238-
.get(0);
231+
&[&to_process.id],
232+
)?
233+
.get(0);
239234

240-
if attempt >= self.max_attempts {
241-
self.metrics.failed_builds.inc();
242-
}
235+
if attempt >= self.max_attempts {
236+
self.metrics.failed_builds.inc();
237+
}
238+
Ok(())
239+
};
243240

244-
report_error(&e);
241+
match res {
242+
Ok(BuildPackageSummary {
243+
should_reattempt: false,
244+
successful: _,
245+
}) => {
246+
transaction.execute("DELETE FROM queue WHERE id = $1;", &[&to_process.id])?;
247+
}
248+
Ok(BuildPackageSummary {
249+
should_reattempt: true,
250+
successful: _,
251+
}) => {
252+
increase_attempt_count()?;
253+
}
254+
Err(e) => {
255+
increase_attempt_count()?;
256+
report_error(&e.context(format!(
257+
"Failed to build package {}-{} from queue",
258+
to_process.name, to_process.version
259+
)))
245260
}
246261
}
247262

@@ -521,8 +536,7 @@ impl BuildQueue {
521536
return Err(err);
522537
}
523538

524-
builder.build_package(&krate.name, &krate.version, kind)?;
525-
Ok(())
539+
builder.build_package(&krate.name, &krate.version, kind)
526540
})?;
527541

528542
Ok(processed)
@@ -644,7 +658,7 @@ mod tests {
644658
queue.process_next_crate(|krate| {
645659
assert_eq!(krate.name, "krate");
646660
handled = true;
647-
Ok(())
661+
Ok(BuildPackageSummary::default())
648662
})?;
649663

650664
assert!(handled);
@@ -680,7 +694,7 @@ mod tests {
680694
let assert_next = |name| -> Result<()> {
681695
queue.process_next_crate(|krate| {
682696
assert_eq!(name, krate.name);
683-
Ok(())
697+
Ok(BuildPackageSummary::default())
684698
})?;
685699
Ok(())
686700
};
@@ -720,7 +734,7 @@ mod tests {
720734
let mut called = false;
721735
queue.process_next_crate(|_| {
722736
called = true;
723-
Ok(())
737+
Ok(BuildPackageSummary::default())
724738
})?;
725739
assert!(!called, "there were still items in the queue");
726740

@@ -755,7 +769,7 @@ mod tests {
755769

756770
queue.process_next_crate(|krate| {
757771
assert_eq!("will_succeed", krate.name);
758-
Ok(())
772+
Ok(BuildPackageSummary::default())
759773
})?;
760774

761775
let queued_invalidations = cdn::queued_or_active_crate_invalidations(&mut *conn)?;
@@ -793,7 +807,7 @@ mod tests {
793807

794808
queue.process_next_crate(|krate| {
795809
assert_eq!("foo", krate.name);
796-
Ok(())
810+
Ok(BuildPackageSummary::default())
797811
})?;
798812
assert_eq!(queue.pending_count()?, 1);
799813

@@ -816,7 +830,7 @@ mod tests {
816830

817831
queue.process_next_crate(|krate| {
818832
assert_eq!("bar", krate.name);
819-
Ok(())
833+
Ok(BuildPackageSummary::default())
820834
})?;
821835
assert_eq!(queue.prioritized_count()?, 1);
822836

@@ -841,7 +855,7 @@ mod tests {
841855
);
842856

843857
while queue.pending_count()? > 0 {
844-
queue.process_next_crate(|_| Ok(()))?;
858+
queue.process_next_crate(|_| Ok(BuildPackageSummary::default()))?;
845859
}
846860
assert!(queue.pending_count_by_priority()?.is_empty());
847861

@@ -850,7 +864,44 @@ mod tests {
850864
}
851865

852866
#[test]
853-
fn test_failed_count() {
867+
fn test_failed_count_for_reattempts() {
868+
const MAX_ATTEMPTS: u16 = 3;
869+
crate::test::wrapper(|env| {
870+
env.override_config(|config| {
871+
config.build_attempts = MAX_ATTEMPTS;
872+
config.delay_between_build_attempts = Duration::ZERO;
873+
});
874+
let queue = env.build_queue();
875+
876+
assert_eq!(queue.failed_count()?, 0);
877+
queue.add_crate("foo", "1.0.0", -100, None)?;
878+
assert_eq!(queue.failed_count()?, 0);
879+
queue.add_crate("bar", "1.0.0", 0, None)?;
880+
881+
for _ in 0..MAX_ATTEMPTS {
882+
assert_eq!(queue.failed_count()?, 0);
883+
queue.process_next_crate(|krate| {
884+
assert_eq!("foo", krate.name);
885+
Ok(BuildPackageSummary {
886+
should_reattempt: true,
887+
..Default::default()
888+
})
889+
})?;
890+
}
891+
assert_eq!(queue.failed_count()?, 1);
892+
893+
queue.process_next_crate(|krate| {
894+
assert_eq!("bar", krate.name);
895+
Ok(BuildPackageSummary::default())
896+
})?;
897+
assert_eq!(queue.failed_count()?, 1);
898+
899+
Ok(())
900+
});
901+
}
902+
903+
#[test]
904+
fn test_failed_count_after_error() {
854905
const MAX_ATTEMPTS: u16 = 3;
855906
crate::test::wrapper(|env| {
856907
env.override_config(|config| {
@@ -875,7 +926,7 @@ mod tests {
875926

876927
queue.process_next_crate(|krate| {
877928
assert_eq!("bar", krate.name);
878-
Ok(())
929+
Ok(BuildPackageSummary::default())
879930
})?;
880931
assert_eq!(queue.failed_count()?, 1);
881932

src/docbuilder/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ mod rustwide_builder;
33

44
pub(crate) use self::limits::Limits;
55
pub(crate) use self::rustwide_builder::DocCoverage;
6-
pub use self::rustwide_builder::{PackageKind, RustwideBuilder};
6+
pub use self::rustwide_builder::{BuildPackageSummary, PackageKind, RustwideBuilder};

0 commit comments

Comments
 (0)