Skip to content

Commit 3758089

Browse files
committed
Feat; mark benchmark requests as complete
1 parent 603527a commit 3758089

File tree

6 files changed

+142
-3
lines changed

6 files changed

+142
-3
lines changed

database/schema.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,36 @@ Columns:
313313
execute.
314314
* **is_active** (`boolean NOT NULL`): For controlling whether the collector is
315315
active for use. Useful for adding/removing collectors.
316+
317+
### job_queue
318+
319+
This table stores ephemeral benchmark jobs, which specifically tell the
320+
collector which benchmarks it should execute. The jobs will be kept in the
321+
table for ~30 days after being completed, so that we can quickly figure out
322+
what master parent jobs we need to backfill when handling try builds.
323+
324+
Columns:
325+
326+
- **id** (`bigint` / `serial`): Primary-key identifier for the job row;
327+
auto-increments with each new job.
328+
- **request_id** (`bigint`): References the parent benchmark request that
329+
spawned this job.
330+
- **target** (`text NOT NULL`): Hardware/ISA the benchmarks must run on
331+
(e.g. AArch64, x86_64).
332+
- **backend** (`text NOT NULL`): Code generation backend the collector should
333+
test (e.g. llvm, cranelift).
334+
- **benchmark_set** (`int NOT NULL`): ID of the predefined benchmark suite to
335+
execute.
336+
- **collector_id** (`text`): Id of the collector that claimed the job
337+
(populated once the job is started).
338+
- **created_at** (`timestamptz NOT NULL`): Datetime when the job was queued.
339+
- **started_at** (`timestamptz`): Datetime when the collector actually began
340+
running the benchmarks; NULL until the job is claimed.
341+
- **completed_at** (`timestampt`): Datetime when the collector finished
342+
(successfully or otherwise); used to purge rows after ~30 days.
343+
- **status** (`text NOT NULL`): Current job state. `queued`, `in_progress`,
344+
`success`, or `failure`.
345+
- **retry** (`int NOT NULL`): Number of times the job has been re-queued after
346+
a failure; 0 on the first attempt.
347+
- **error** (`text`): Optional error message or stack trace from the last
348+
failed run; NULL when the job succeeded.

database/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,10 @@ impl BenchmarkRequest {
10261026
.collect::<Result<Vec<_>, _>>()
10271027
.map_err(|e| anyhow::anyhow!("Invalid backend: {e}"))
10281028
}
1029+
1030+
pub fn is_completed(&self) -> bool {
1031+
matches!(self.status, BenchmarkRequestStatus::Completed { .. })
1032+
}
10291033
}
10301034

10311035
/// Cached information about benchmark requests in the DB
@@ -1047,6 +1051,11 @@ impl BenchmarkRequestIndex {
10471051
pub fn completed_requests(&self) -> &HashSet<String> {
10481052
&self.completed
10491053
}
1054+
1055+
pub fn add_tag(&mut self, tag: &str) {
1056+
self.all.insert(tag.to_string());
1057+
self.completed.insert(tag.to_string());
1058+
}
10501059
}
10511060

10521061
#[derive(Debug, Clone, PartialEq)]

database/src/pool.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ pub trait Connection: Send + Sync {
253253
target: &Target,
254254
benchmark_set: &BenchmarkSet,
255255
) -> anyhow::Result<Option<BenchmarkJob>>;
256+
257+
/// Try and mark the benchmark_request as completed. Will return `true` if
258+
/// it has been marked as completed else `false` meaning there was no change
259+
async fn mark_benchmark_request_as_completed(
260+
&self,
261+
benchmark_request: &mut BenchmarkRequest,
262+
) -> anyhow::Result<bool>;
256263
}
257264

258265
#[async_trait::async_trait]

database/src/pool/postgres.rs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::{
55
BenchmarkRequest, BenchmarkRequestIndex, BenchmarkRequestStatus, BenchmarkRequestType,
66
BenchmarkSet, CodegenBackend, CollectionId, CollectorConfig, Commit, CommitType,
77
CompileBenchmark, Date, Index, Profile, QueuedCommit, Scenario, Target,
8-
BENCHMARK_JOB_STATUS_IN_PROGRESS_STR, BENCHMARK_JOB_STATUS_QUEUED_STR,
8+
BENCHMARK_JOB_STATUS_FAILURE_STR, BENCHMARK_JOB_STATUS_IN_PROGRESS_STR,
9+
BENCHMARK_JOB_STATUS_QUEUED_STR, BENCHMARK_JOB_STATUS_SUCCESS_STR,
910
BENCHMARK_REQUEST_MASTER_STR, BENCHMARK_REQUEST_RELEASE_STR,
1011
BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR, BENCHMARK_REQUEST_STATUS_COMPLETED_STR,
1112
BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR, BENCHMARK_REQUEST_STATUS_WAITING_FOR_ARTIFACTS_STR,
@@ -1887,6 +1888,82 @@ where
18871888
}
18881889
}
18891890
}
1891+
1892+
async fn mark_benchmark_request_as_completed(
1893+
&self,
1894+
benchmark_request: &mut BenchmarkRequest,
1895+
) -> anyhow::Result<bool> {
1896+
anyhow::ensure!(
1897+
benchmark_request.tag().is_some(),
1898+
"Benchmark request has no tag"
1899+
);
1900+
anyhow::ensure!(
1901+
benchmark_request.status == BenchmarkRequestStatus::InProgress,
1902+
"Can only mark benchmark request whos status is in_progress as complete"
1903+
);
1904+
1905+
// Find if the benchmark is completed and update it's status to completed
1906+
// in one SQL block
1907+
let row = self
1908+
.conn()
1909+
.query_opt(
1910+
"
1911+
UPDATE
1912+
benchmark_request
1913+
SET
1914+
status = $1,
1915+
completed_at = NOW()
1916+
WHERE
1917+
banchmark_request.tag = $2
1918+
AND benchmark_request.status != $1
1919+
AND NOT EXISTS (
1920+
SELECT
1921+
1
1922+
FROM
1923+
job_queue
1924+
WHERE
1925+
request_tag = benchmark_request.tag
1926+
AND status NOT IN ($3, $4)
1927+
)
1928+
AND (
1929+
benchmark_request.parent_sha IS NULL
1930+
OR NOT EXISTS (
1931+
SELECT
1932+
1
1933+
FROM
1934+
job_queue
1935+
JOIN
1936+
benchmark_request AS parent_request
1937+
ON
1938+
parent_request.tag = benchmark_request.parent_tag
1939+
WHERE
1940+
job_queue.request_tag = parent_request.tag
1941+
AND job_queue.status NOT IN ($3, $4)
1942+
)
1943+
)
1944+
RETURNING
1945+
benchmark_request.completed_at;
1946+
",
1947+
&[
1948+
&BENCHMARK_REQUEST_STATUS_COMPLETED_STR,
1949+
&benchmark_request.tag(),
1950+
&BENCHMARK_JOB_STATUS_SUCCESS_STR,
1951+
&BENCHMARK_JOB_STATUS_FAILURE_STR,
1952+
],
1953+
)
1954+
.await
1955+
.context("Failed to mark benchmark_request as completed")?;
1956+
// The affected id is returned by the query thus we can use the row's
1957+
// presence to determine if the request was marked as completed
1958+
if let Some(row) = row {
1959+
let completed_at = row.get::<_, DateTime<Utc>>(0);
1960+
// Also mutate our object
1961+
benchmark_request.status = BenchmarkRequestStatus::Completed { completed_at };
1962+
Ok(true)
1963+
} else {
1964+
Ok(false)
1965+
}
1966+
}
18901967
}
18911968

18921969
fn parse_artifact_id(ty: &str, sha: &str, date: Option<DateTime<Utc>>) -> ArtifactId {

database/src/pool/sqlite.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,13 @@ impl Connection for SqliteConnection {
13531353
) -> anyhow::Result<CollectorConfig> {
13541354
no_queue_implementation_abort!()
13551355
}
1356+
1357+
async fn mark_benchmark_request_as_completed(
1358+
&self,
1359+
_benchmark_request: &mut BenchmarkRequest,
1360+
) -> anyhow::Result<bool> {
1361+
no_queue_implementation_abort!()
1362+
}
13561363
}
13571364

13581365
fn parse_artifact_id(ty: &str, sha: &str, date: Option<i64>) -> ArtifactId {

site/src/job_queue/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,20 @@ async fn try_enqueue_next_benchmark_request(
246246
let queue = build_queue(conn, index).await?;
247247

248248
#[allow(clippy::never_loop)]
249-
for request in queue {
249+
for mut request in queue {
250250
match request.status() {
251251
BenchmarkRequestStatus::ArtifactsReady => {
252252
enqueue_benchmark_request(conn, &request).await?;
253253
break;
254254
}
255255
BenchmarkRequestStatus::InProgress => {
256-
// TODO: Try to mark as completed
256+
if conn
257+
.mark_benchmark_request_as_completed(&mut request)
258+
.await?
259+
{
260+
index.add_tag(request.tag().unwrap());
261+
continue;
262+
}
257263
break;
258264
}
259265
BenchmarkRequestStatus::WaitingForArtifacts

0 commit comments

Comments
 (0)