Skip to content

Commit 7ab435d

Browse files
committed
Use the new job queue for request duration estimation
1 parent 1240d39 commit 7ab435d

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

site/src/github.rs

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ pub mod client;
22
pub mod comparison_summary;
33

44
use crate::api::github::Commit;
5-
use crate::job_queue::should_use_job_queue;
6-
use crate::load::{MissingReason, SiteCtxt, TryCommit};
5+
use crate::job_queue::{build_queue, should_use_job_queue};
6+
use crate::load::{SiteCtxt, TryCommit};
7+
use chrono::Utc;
78
use serde::Deserialize;
89
use std::sync::LazyLock;
910
use std::time::Duration;
@@ -22,7 +23,7 @@ pub const COMMENT_MARK_TEMPORARY: &str = "<!-- rust-timer: temporary -->";
2223
pub const COMMENT_MARK_ROLLUP: &str = "<!-- rust-timer: rollup -->";
2324

2425
pub use comparison_summary::post_finished;
25-
use database::Connection;
26+
use database::{BenchmarkJobStatus, BenchmarkRequestStatus, Connection};
2627

2728
/// Enqueues try build artifacts and posts a message about them on the original rollup PR
2829
pub async fn unroll_rollup(
@@ -283,7 +284,9 @@ pub async fn enqueue_shas(
283284
}
284285

285286
let (preceding_artifacts, expected_duration) =
286-
estimate_queue_info(ctxt, conn.as_ref(), &try_commit).await;
287+
estimate_queue_info(conn.as_ref(), &try_commit)
288+
.await
289+
.map_err(|e| format!("{e:?}"))?;
287290

288291
let verb = if preceding_artifacts == 1 {
289292
"is"
@@ -317,35 +320,44 @@ It will probably take at least ~{:.1} hours until the benchmark run finishes."#,
317320
/// Counts how many artifacts are in the queue before the specified commit, and what is the expected
318321
/// duration until the specified commit will be finished.
319322
async fn estimate_queue_info(
320-
ctxt: &SiteCtxt,
321323
conn: &dyn Connection,
322324
commit: &TryCommit,
323-
) -> (u64, Duration) {
324-
let queue = ctxt.missing_commits().await;
325+
) -> anyhow::Result<(u64, Duration)> {
326+
let queue = build_queue(conn).await?;
325327

326328
// Queue without in-progress artifacts
327-
let queue_waiting: Vec<_> = queue
328-
.into_iter()
329-
.filter_map(|(c, reason)| match reason {
330-
MissingReason::InProgress(_) if c.sha != commit.sha => None,
331-
_ => Some(c),
329+
let queue_waiting = queue
330+
.iter()
331+
.filter(|req| match req.status() {
332+
BenchmarkRequestStatus::WaitingForArtifacts
333+
| BenchmarkRequestStatus::ArtifactsReady => true,
334+
BenchmarkRequestStatus::Completed { .. } | BenchmarkRequestStatus::InProgress => false,
332335
})
333-
.collect();
336+
.collect::<Vec<_>>();
334337

335338
// Measure expected duration of waiting artifacts
336339
// How many commits are waiting (i.e. not running) in the queue before the specified commit?
337340
let preceding_waiting = queue_waiting
338341
.iter()
339-
.position(|c| c.sha == commit.sha())
342+
.position(|c| c.tag() == Some(commit.sha()))
340343
.unwrap_or(queue_waiting.len().saturating_sub(1)) as u64;
341344

342345
// Guess the expected full run duration of a waiting commit
343346
let last_duration = conn
344-
.last_n_artifact_collections(1)
345-
.await
347+
.get_last_n_completed_benchmark_requests(1)
348+
.await?
346349
.into_iter()
347350
.next()
348-
.map(|collection| collection.duration)
351+
.map(|collection| match collection.request.status() {
352+
BenchmarkRequestStatus::WaitingForArtifacts
353+
| BenchmarkRequestStatus::ArtifactsReady
354+
| BenchmarkRequestStatus::InProgress => {
355+
unreachable!(
356+
"Non-completed request returned from `get_last_n_completed_benchmark_requests`"
357+
)
358+
}
359+
BenchmarkRequestStatus::Completed { duration, .. } => duration,
360+
})
349361
.unwrap_or(Duration::ZERO);
350362

351363
// Guess that the duration will take about an hour if we don't have data or it's
@@ -355,17 +367,46 @@ async fn estimate_queue_info(
355367
let mut expected_duration = last_duration * (preceding_waiting + 1) as u32;
356368
let mut preceding = preceding_waiting;
357369

358-
// Add in-progress artifact duration and count (if any)
359-
if let Some(aid) = conn.in_progress_artifacts().await.pop() {
370+
// Add in-progress artifact duration and count
371+
let now = Utc::now();
372+
let jobs = conn.get_jobs_of_in_progress_benchmark_requests().await?;
373+
for req in queue
374+
.into_iter()
375+
.filter(|req| matches!(req.status(), BenchmarkRequestStatus::InProgress))
376+
{
377+
let Some(tag) = req.tag() else {
378+
continue;
379+
};
380+
if tag == commit.sha {
381+
continue;
382+
}
383+
let Some(jobs) = jobs.get(tag) else {
384+
preceding += 1;
385+
expected_duration += last_duration;
386+
continue;
387+
};
388+
let duration_elapsed = jobs
389+
.iter()
390+
.map(|j| match j.status() {
391+
BenchmarkJobStatus::Queued => Duration::ZERO,
392+
BenchmarkJobStatus::InProgress { started_at, .. } => now
393+
.signed_duration_since(started_at)
394+
.to_std()
395+
.unwrap_or_default(),
396+
BenchmarkJobStatus::Completed {
397+
completed_at,
398+
started_at,
399+
..
400+
} => completed_at
401+
.signed_duration_since(started_at)
402+
.to_std()
403+
.unwrap_or_default(),
404+
})
405+
.sum::<Duration>();
360406
preceding += 1;
361-
expected_duration += conn
362-
.in_progress_steps(&aid)
363-
.await
364-
.into_iter()
365-
.map(|s| s.expected.saturating_sub(s.duration))
366-
.sum();
407+
expected_duration += last_duration.saturating_sub(duration_elapsed);
367408
}
368-
(preceding, expected_duration)
409+
Ok((preceding, expected_duration))
369410
}
370411

371412
#[derive(Debug, Deserialize)]

site/src/job_queue/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,14 @@ fn sort_benchmark_requests(pending: PendingBenchmarkRequests) -> Vec<BenchmarkRe
170170
/// after an in-progress request is finished, the ordering of the rest of the queue does not
171171
/// change (unless some other request was added to the queue in the meantime).
172172
///
173-
/// Does not consider requests that are waiting for artifacts or that are alredy completed.
173+
/// Does not consider requests that are waiting for artifacts or that are already completed.
174+
///
175+
/// The returned order is:
176+
/// - In progress (if present)
177+
/// - First to be benchmarked
178+
/// - Second to be benchmarked
179+
/// - Third to be benchmarked
180+
/// - ...
174181
pub async fn build_queue(
175182
conn: &dyn database::pool::Connection,
176183
) -> anyhow::Result<Vec<BenchmarkRequest>> {

0 commit comments

Comments
 (0)