Skip to content

Commit 62e2704

Browse files
authored
Merge pull request #2192 from Jamesbarford/feat/create-release-benchmark-requests
Feat; add releases to the benchmark_request queue
2 parents 1dcd547 + 069f182 commit 62e2704

File tree

1 file changed

+161
-4
lines changed

1 file changed

+161
-4
lines changed

site/src/job_queue.rs

Lines changed: 161 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
use std::{str::FromStr, sync::Arc};
1+
use std::{
2+
path::Path,
3+
str::FromStr,
4+
sync::{Arc, LazyLock},
5+
};
26

37
use crate::load::{partition_in_place, SiteCtxt};
4-
use chrono::Utc;
8+
use chrono::{DateTime, NaiveDate, Utc};
59
use database::{BenchmarkRequest, BenchmarkRequestStatus, BenchmarkRequestType};
610
use hashbrown::HashSet;
711
use parking_lot::RwLock;
12+
use regex::Regex;
813
use tokio::time::{self, Duration};
914

1015
/// Store the latest master commits or do nothing if all of them are
@@ -36,6 +41,94 @@ async fn create_benchmark_request_master_commits(
3641
Ok(())
3742
}
3843

44+
/// Parses strings in the following formats extracting the Date & release tag
45+
/// `static.rust-lang.org/dist/2016-05-24/channel-rust-1.9.0.toml`
46+
/// `static.rust-lang.org/dist/2016-05-31/channel-rust-nightly.toml`
47+
/// `static.rust-lang.org/dist/2016-06-01/channel-rust-beta.toml`
48+
/// `static.rust-lang.org/dist/2025-06-26/channel-rust-1.89-beta.toml`
49+
/// `static.rust-lang.org/dist/2025-06-26/channel-rust-1.89.0-beta.toml`
50+
/// `static.rust-lang.org/dist/2025-06-26/channel-rust-1.89.0-beta.2.toml`
51+
fn parse_release_string(url: &str) -> Option<(String, DateTime<Utc>)> {
52+
static VERSION_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(\d+\.\d+\.\d+)").unwrap());
53+
54+
// Grab ".../YYYY-MM-DD/FILE.toml" components with Path helpers.
55+
let file = Path::new(url).file_name().and_then(|n| n.to_str())?;
56+
57+
let date_str = Path::new(url)
58+
.parent()
59+
.and_then(Path::file_name)
60+
.and_then(|n| n.to_str())?;
61+
62+
// No other beta releases are recognized as toolchains.
63+
//
64+
// We also have names like this:
65+
//
66+
// * channel-rust-1.75-beta.toml
67+
// * channel-rust-1.75.0-beta.toml
68+
// * channel-rust-1.75.0-beta.1.toml
69+
//
70+
// Which should get ignored for now, they're not consumable via rustup yet.
71+
if file.contains("beta") && file != "channel-rust-beta.toml" {
72+
return None;
73+
}
74+
75+
// Parse the YYYY-MM-DD segment and stamp it with *current* UTC time.
76+
if let Ok(naive) = NaiveDate::parse_from_str(date_str, "%Y-%m-%d") {
77+
let published = naive
78+
.and_hms_opt(0, 0, 0)
79+
.expect("valid HMS")
80+
.and_local_timezone(Utc)
81+
.single()
82+
.unwrap();
83+
84+
// Special-case the rolling beta channel.
85+
if file == "channel-rust-beta.toml" {
86+
return Some((format!("beta-{date_str}"), published));
87+
}
88+
89+
// Otherwise pull out a semver like "1.70.0" and return it.
90+
if let Some(cap) = VERSION_RE.captures(file).and_then(|m| m.get(1)) {
91+
return Some((cap.as_str().to_owned(), published));
92+
}
93+
}
94+
95+
None
96+
}
97+
98+
/// Store the latest release commits or do nothing if all of them are
99+
/// already in the database
100+
async fn create_benchmark_request_releases(
101+
conn: &dyn database::pool::Connection,
102+
) -> anyhow::Result<()> {
103+
let releases: String = reqwest::get("https://static.rust-lang.org/manifests.txt")
104+
.await?
105+
.text()
106+
.await?;
107+
// TODO; delete at some point in the future
108+
let cutoff: chrono::DateTime<Utc> = chrono::DateTime::from_str("2025-06-01T00:00:00.000Z")?;
109+
110+
let releases: Vec<_> = releases
111+
.lines()
112+
.rev()
113+
.filter_map(parse_release_string)
114+
.take(20)
115+
.collect();
116+
117+
for (name, date_time) in releases {
118+
if date_time >= cutoff {
119+
let release_request = BenchmarkRequest::create_release(
120+
&name,
121+
date_time,
122+
BenchmarkRequestStatus::ArtifactsReady,
123+
"",
124+
"",
125+
);
126+
conn.insert_benchmark_request(&release_request).await;
127+
}
128+
}
129+
Ok(())
130+
}
131+
39132
/// Sorts try and master requests that are in the `ArtifactsReady` status.
40133
/// Doesn't consider in-progress requests or release artifacts.
41134
fn sort_benchmark_requests(done: &HashSet<String>, request_queue: &mut [BenchmarkRequest]) {
@@ -186,6 +279,8 @@ async fn cron_enqueue_jobs(site_ctxt: &Arc<SiteCtxt>) -> anyhow::Result<()> {
186279
let mut conn = site_ctxt.conn().await;
187280
// Put the master commits into the `benchmark_requests` queue
188281
create_benchmark_request_master_commits(site_ctxt, &*conn).await?;
282+
// Put the releases into the `benchmark_requests` queue
283+
create_benchmark_request_releases(&*conn).await?;
189284
enqueue_next_job(&mut *conn).await?;
190285
Ok(())
191286
}
@@ -213,10 +308,21 @@ pub async fn cron_main(site_ctxt: Arc<RwLock<Option<Arc<SiteCtxt>>>>, seconds: u
213308
#[cfg(test)]
214309
mod tests {
215310
use super::*;
216-
use chrono::{Datelike, Duration, TimeZone, Utc};
217-
311+
use chrono::{Datelike, Duration, NaiveDate, TimeZone, Utc};
218312
use database::tests::run_postgres_test;
219313

314+
/// Helper: unwrap the Option, panic otherwise.
315+
fn tag(url: &str) -> String {
316+
parse_release_string(url)
317+
.expect("Some") // Option<_>
318+
.0 // take the tag
319+
}
320+
321+
/// Helper: unwrap the DateTime and keep only the YYYY-MM-DD part
322+
fn day(url: &str) -> NaiveDate {
323+
parse_release_string(url).expect("Some").1.date_naive()
324+
}
325+
220326
fn days_ago(day_str: &str) -> chrono::DateTime<Utc> {
221327
// Walk backwards until the first non-digit, then slice
222328
let days = day_str
@@ -602,4 +708,55 @@ mod tests {
602708
})
603709
.await;
604710
}
711+
712+
#[test]
713+
fn parses_stable_versions() {
714+
assert_eq!(
715+
tag("static.rust-lang.org/dist/2016-05-24/channel-rust-1.9.0.toml"),
716+
"1.9.0"
717+
);
718+
assert_eq!(
719+
day("static.rust-lang.org/dist/2016-05-24/channel-rust-1.9.0.toml"),
720+
NaiveDate::from_ymd_opt(2016, 5, 24).unwrap()
721+
);
722+
723+
assert_eq!(
724+
tag("static.rust-lang.org/dist/2025-06-26/channel-rust-1.88.0.toml"),
725+
"1.88.0"
726+
);
727+
assert_eq!(
728+
day("static.rust-lang.org/dist/2025-06-26/channel-rust-1.88.0.toml"),
729+
NaiveDate::from_ymd_opt(2025, 6, 26).unwrap()
730+
);
731+
}
732+
733+
#[test]
734+
fn parses_plain_beta_channel() {
735+
let want = "beta-2016-06-01";
736+
let url = "static.rust-lang.org/dist/2016-06-01/channel-rust-beta.toml";
737+
738+
assert_eq!(tag(url), want);
739+
assert_eq!(day(url), NaiveDate::from_ymd_opt(2016, 6, 1).unwrap());
740+
}
741+
742+
#[test]
743+
fn skips_unconsumable_channels() {
744+
// nightly never returns Anything
745+
assert!(parse_release_string(
746+
"static.rust-lang.org/dist/2016-05-31/channel-rust-nightly.toml"
747+
)
748+
.is_none());
749+
750+
// versioned-beta artefacts are skipped too
751+
for should_ignore in [
752+
"static.rust-lang.org/dist/2025-06-26/channel-rust-1.89-beta.toml",
753+
"static.rust-lang.org/dist/2025-06-26/channel-rust-1.89.0-beta.toml",
754+
"static.rust-lang.org/dist/2025-06-26/channel-rust-1.89.0-beta.2.toml",
755+
] {
756+
assert!(
757+
parse_release_string(should_ignore).is_none(),
758+
"{should_ignore} should be ignored"
759+
);
760+
}
761+
}
605762
}

0 commit comments

Comments
 (0)