Skip to content

Feat - cron queue for master commits #2163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 19, 2025
172 changes: 172 additions & 0 deletions database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,3 +798,175 @@ pub struct ArtifactCollection {
pub duration: Duration,
pub end_time: DateTime<Utc>,
}

#[derive(Debug)]
pub enum BenchmarkRequestStatus {
WaitingForArtifacts,
WaitingForParent,
InProgress,
Completed,
}

impl fmt::Display for BenchmarkRequestStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BenchmarkRequestStatus::WaitingForArtifacts => write!(f, "waiting_for_artifacts"),
BenchmarkRequestStatus::WaitingForParent => write!(f, "waiting_for_parent"),
BenchmarkRequestStatus::InProgress => write!(f, "in_progress"),
BenchmarkRequestStatus::Completed => write!(f, "completed"),
}
}
}

#[derive(Debug)]
pub enum BenchmarkRequestType {
/// A Try commit
Try {
sha: String,
parent_sha: String,
pr: u32,
},
/// A Master commit
Master {
sha: String,
parent_sha: String,
pr: u32,
},
/// A release only has a tag
Release { tag: String },
}

impl BenchmarkRequestType {
pub fn commit_type_str(&self) -> &str {
match self {
BenchmarkRequestType::Try {
sha: _,
parent_sha: _,
pr: _,
} => "try",
BenchmarkRequestType::Master {
sha: _,
parent_sha: _,
pr: _,
} => "master",
BenchmarkRequestType::Release { tag: _ } => "release",
}
}
}

impl fmt::Display for BenchmarkRequestType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BenchmarkRequestType::Try { .. } => write!(f, "try"),
BenchmarkRequestType::Master { .. } => write!(f, "master"),
BenchmarkRequestType::Release { tag: _ } => write!(f, "release"),
}
}
}

#[derive(Debug)]
pub struct BenchmarkRequest {
pub commit_type: BenchmarkRequestType,
pub created_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
pub status: BenchmarkRequestStatus,
pub backends: String,
pub profiles: String,
}

impl BenchmarkRequest {
pub fn create_release(
tag: &str,
created_at: DateTime<Utc>,
status: BenchmarkRequestStatus,
backends: &str,
profiles: &str,
) -> Self {
Self {
commit_type: BenchmarkRequestType::Release {
tag: tag.to_string(),
},
created_at,
completed_at: None,
status,
backends: backends.to_string(),
profiles: profiles.to_string(),
}
}

pub fn create_try(
sha: &str,
parent_sha: &str,
pr: u32,
created_at: DateTime<Utc>,
status: BenchmarkRequestStatus,
backends: &str,
profiles: &str,
) -> Self {
Self {
commit_type: BenchmarkRequestType::Try {
pr,
sha: sha.to_string(),
parent_sha: parent_sha.to_string(),
},
created_at,
completed_at: None,
status,
backends: backends.to_string(),
profiles: profiles.to_string(),
}
}

pub fn create_master(
sha: &str,
parent_sha: &str,
pr: u32,
created_at: DateTime<Utc>,
status: BenchmarkRequestStatus,
backends: &str,
profiles: &str,
) -> Self {
Self {
commit_type: BenchmarkRequestType::Master {
pr,
sha: sha.to_string(),
parent_sha: parent_sha.to_string(),
},
created_at,
completed_at: None,
status,
backends: backends.to_string(),
profiles: profiles.to_string(),
}
}

/// Get either the `sha` for a `try` or `master` commit or a `tag` for a
/// `release`
pub fn tag(&self) -> &str {
match &self.commit_type {
BenchmarkRequestType::Try { sha, .. } | BenchmarkRequestType::Master { sha, .. } => sha,
BenchmarkRequestType::Release { tag } => tag,
}
}

pub fn pr(&self) -> Option<&u32> {
match &self.commit_type {
BenchmarkRequestType::Try { pr, .. } | BenchmarkRequestType::Master { pr, .. } => {
Some(pr)
}
BenchmarkRequestType::Release { tag: _ } => None,
}
}

pub fn commit_type(&self) -> &str {
self.commit_type.commit_type_str()
}

pub fn parent_sha(&self) -> Option<&str> {
match &self.commit_type {
BenchmarkRequestType::Try { parent_sha, .. }
| BenchmarkRequestType::Master { parent_sha, .. } => Some(parent_sha),
BenchmarkRequestType::Release { tag: _ } => None,
}
}
}
58 changes: 56 additions & 2 deletions database/src/pool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
ArtifactCollection, ArtifactId, ArtifactIdNumber, CodegenBackend, CompileBenchmark, Target,
ArtifactCollection, ArtifactId, ArtifactIdNumber, BenchmarkRequest, CodegenBackend,
CompileBenchmark, Target,
};
use crate::{CollectionId, Index, Profile, QueuedCommit, Scenario, Step};
use chrono::{DateTime, Utc};
Expand Down Expand Up @@ -178,6 +179,10 @@ pub trait Connection: Send + Sync {

/// Removes all data associated with the given artifact.
async fn purge_artifact(&self, aid: &ArtifactId);

/// Add an item to the `benchmark_requests`, if the `benchmark_request`
/// exists it will be ignored
async fn insert_benchmark_request(&self, benchmark_request: &BenchmarkRequest);
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -301,7 +306,10 @@ mod tests {
use std::str::FromStr;

use super::*;
use crate::{tests::run_db_test, Commit, CommitType, Date};
use crate::{
tests::{run_db_test, run_postgres_test},
BenchmarkRequestStatus, Commit, CommitType, Date,
};

/// Create a Commit
fn create_commit(commit_sha: &str, time: chrono::DateTime<Utc>, r#type: CommitType) -> Commit {
Expand Down Expand Up @@ -370,4 +378,50 @@ mod tests {
})
.await;
}

#[tokio::test]
async fn insert_benchmark_requests() {
run_postgres_test(|ctx| async {
let db = ctx.db_client();
let time = chrono::DateTime::from_str("2021-09-01T00:00:00.000Z").unwrap();
let master_benchmark_request = BenchmarkRequest::create_master(
"a-sha-1",
"parent-sha-1",
42,
time,
BenchmarkRequestStatus::WaitingForParent,
"llvm",
"",
);

let try_benchmark_request = BenchmarkRequest::create_try(
"b-sha-2",
"parent-sha-2",
32,
time,
BenchmarkRequestStatus::WaitingForParent,
"cranelift",
"",
);

let release_benchmark_request = BenchmarkRequest::create_release(
"1.8.0",
time,
BenchmarkRequestStatus::WaitingForParent,
"cranelift,llvm",
"",
);

let db = db.connection().await;
db.insert_benchmark_request(&master_benchmark_request).await;
db.insert_benchmark_request(&try_benchmark_request).await;
db.insert_benchmark_request(&release_benchmark_request)
.await;
// duplicate insert
db.insert_benchmark_request(&master_benchmark_request).await;

Ok(ctx)
})
.await;
}
}
52 changes: 50 additions & 2 deletions database/src/pool/postgres.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::pool::{Connection, ConnectionManager, ManagedConnection, Transaction};
use crate::{
ArtifactCollection, ArtifactId, ArtifactIdNumber, Benchmark, CodegenBackend, CollectionId,
Commit, CommitType, CompileBenchmark, Date, Index, Profile, QueuedCommit, Scenario, Target,
ArtifactCollection, ArtifactId, ArtifactIdNumber, Benchmark, BenchmarkRequest, CodegenBackend,
CollectionId, Commit, CommitType, CompileBenchmark, Date, Index, Profile, QueuedCommit,
Scenario, Target,
};
use anyhow::Context as _;
use chrono::{DateTime, TimeZone, Utc};
Expand Down Expand Up @@ -285,6 +286,21 @@ static MIGRATIONS: &[&str] = &[
alter table pstat_series drop constraint test_case;
alter table pstat_series add constraint test_case UNIQUE(crate, profile, scenario, backend, target, metric);
"#,
r#"
CREATE TABLE IF NOT EXISTS benchmark_request (
id SERIAL PRIMARY KEY,
tag TEXT NOT NULL UNIQUE,
parent_sha TEXT,
commit_type TEXT NOT NULL,
pr INTEGER,
created_at TIMESTAMPTZ NOT NULL,
completed_at TIMESTAMPTZ,
status TEXT NOT NULL,
backends TEXT NOT NULL,
profiles TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS benchmark_request_status_idx on benchmark_request (status) WHERE status != 'completed';
"#,
];

#[async_trait::async_trait]
Expand Down Expand Up @@ -1365,6 +1381,38 @@ where
.await
.unwrap();
}

async fn insert_benchmark_request(&self, benchmark_request: &BenchmarkRequest) {
self.conn()
.execute(
r#"
INSERT INTO benchmark_request(
tag,
parent_sha,
pr,
commit_type,
status,
created_at,
backends,
profiles
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT DO NOTHING;
"#,
&[
&benchmark_request.tag(),
&benchmark_request.parent_sha(),
&benchmark_request.pr().map(|it| *it as i32),
&benchmark_request.commit_type(),
&benchmark_request.status.to_string(),
&benchmark_request.created_at,
&benchmark_request.backends,
&benchmark_request.profiles,
],
)
.await
.unwrap();
}
}

fn parse_artifact_id(ty: &str, sha: &str, date: Option<DateTime<Utc>>) -> ArtifactId {
Expand Down
8 changes: 6 additions & 2 deletions database/src/pool/sqlite.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::pool::{Connection, ConnectionManager, ManagedConnection, Transaction};
use crate::{
ArtifactCollection, ArtifactId, Benchmark, CodegenBackend, CollectionId, Commit, CommitType,
CompileBenchmark, Date, Profile, Target,
ArtifactCollection, ArtifactId, Benchmark, BenchmarkRequest, CodegenBackend, CollectionId,
Commit, CommitType, CompileBenchmark, Date, Profile, Target,
};
use crate::{ArtifactIdNumber, Index, QueuedCommit};
use chrono::{DateTime, TimeZone, Utc};
Expand Down Expand Up @@ -1252,6 +1252,10 @@ impl Connection for SqliteConnection {
)
.unwrap();
}

async fn insert_benchmark_request(&self, _benchmark_request: &BenchmarkRequest) {
panic!("Queueing for SQLite has not been implemented, if you are wanting to test the queueing functionality please use postgres. Presuming you have docker installed, at the root of the repo you can run `make start-postgres` to spin up a postgres database.");
}
}

fn parse_artifact_id(ty: &str, sha: &str, date: Option<i64>) -> ArtifactId {
Expand Down
14 changes: 11 additions & 3 deletions database/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ impl TestContext {
}
}

/// Runs a test against an actual database.
/// Checks both Postgres and SQLite.
pub(crate) async fn run_db_test<F, Fut>(f: F)
/// Runs a test against an actual postgres database.
pub(crate) async fn run_postgres_test<F, Fut>(f: F)
where
F: Fn(TestContext) -> Fut,
Fut: Future<Output = anyhow::Result<TestContext>>,
Expand All @@ -138,7 +137,16 @@ where
);
}
}
}

/// Runs a test against an actual database.
/// Checks both Postgres and SQLite.
pub(crate) async fn run_db_test<F, Fut>(f: F)
where
F: Fn(TestContext) -> Fut + Clone,
Fut: Future<Output = anyhow::Result<TestContext>>,
{
run_postgres_test(f.clone()).await;
// SQLite
eprintln!("Running test with SQLite");
let ctx = TestContext::new_sqlite().await;
Expand Down
Loading
Loading