Return graph data at /graph/data
This commit is contained in:
parent
3cf444ffc2
commit
3c9fc1ce75
8 changed files with 138 additions and 5 deletions
26
.sqlx/query-039485fead98beb9d088c5bb35679f2ab0409e7e6b51607869ec30ef35240504.json
generated
Normal file
26
.sqlx/query-039485fead98beb9d088c5bb35679f2ab0409e7e6b51607869ec30ef35240504.json
generated
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT hash, committer_date AS \"committer_date: time::OffsetDateTime\" FROM commits ORDER BY committer_date ASC, hash ASC ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "hash",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "committer_date: time::OffsetDateTime",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 0
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "039485fead98beb9d088c5bb35679f2ab0409e7e6b51607869ec30ef35240504"
|
||||
}
|
||||
20
.sqlx/query-4e2f2b25a13b3728db01b7c218e7250441098c60725c081215489bd2ad944fe0.json
generated
Normal file
20
.sqlx/query-4e2f2b25a13b3728db01b7c218e7250441098c60725c081215489bd2ad944fe0.json
generated
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "WITH measurements AS ( SELECT hash, value, MAX(start) FROM runs JOIN run_measurements USING (id) WHERE name = ? GROUP BY hash ) SELECT value FROM commits LEFT JOIN measurements USING (hash) ORDER BY committer_date ASC, hash ASC ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "value",
|
||||
"ordinal": 0,
|
||||
"type_info": "Float"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "4e2f2b25a13b3728db01b7c218e7250441098c60725c081215489bd2ad944fe0"
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ anyhow = "1.0.72"
|
|||
askama = { version = "0.12.0", features = ["with-axum"] }
|
||||
askama_axum = "0.3.0"
|
||||
axum = { version = "0.6.19", features = ["macros", "headers"] }
|
||||
axum-extra = { version = "0.7.7", features = ["typed-routing"] }
|
||||
axum-extra = { version = "0.7.7", features = ["typed-routing", "query"] }
|
||||
bytes = "1.4.0"
|
||||
clap = { version = "4.3.19", features = ["derive", "deprecated"] }
|
||||
directories = "5.0.1"
|
||||
|
|
|
|||
|
|
@ -26,5 +26,8 @@ CREATE TABLE refs (
|
|||
FOREIGN KEY (hash) REFERENCES commits (hash) ON DELETE CASCADE
|
||||
) STRICT;
|
||||
|
||||
CREATE INDEX idx_commits_committer_date_hash
|
||||
ON commits (committer_date, hash);
|
||||
|
||||
CREATE INDEX idx_commit_links_parent_child
|
||||
ON commit_links (parent, child);
|
||||
|
|
|
|||
|
|
@ -32,3 +32,6 @@ CREATE TABLE run_output (
|
|||
PRIMARY KEY (id, idx),
|
||||
FOREIGN KEY (id) REFERENCES runs (id) ON DELETE CASCADE
|
||||
) STRICT;
|
||||
|
||||
CREATE INDEX idx_run_measurements_name_id_value
|
||||
ON run_measurements (name, id, value);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use self::{
|
|||
},
|
||||
pages::{
|
||||
commit::get_commit_by_hash,
|
||||
graph::get_graph,
|
||||
graph::{get_graph, get_graph_data},
|
||||
index::get_index,
|
||||
queue::{get_queue, get_queue_delete, get_queue_inner},
|
||||
run::get_run_by_id,
|
||||
|
|
@ -44,6 +44,7 @@ pub async fn run(server: Server) -> somehow::Result<()> {
|
|||
.typed_get(get_api_worker_repo_by_hash_tree_tar_gz)
|
||||
.typed_get(get_commit_by_hash)
|
||||
.typed_get(get_graph)
|
||||
.typed_get(get_graph_data)
|
||||
.typed_get(get_index)
|
||||
.typed_get(get_queue)
|
||||
.typed_get(get_queue_delete)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use askama::Template;
|
||||
use axum::{extract::State, response::IntoResponse};
|
||||
use axum::{extract::State, response::IntoResponse, Json};
|
||||
use axum_extra::extract::Query;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{Acquire, SqlitePool};
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
server::web::{
|
||||
base::{Base, Link, Tab},
|
||||
paths::PathGraph,
|
||||
paths::{PathGraph, PathGraphData},
|
||||
r#static::GRAPH_JS,
|
||||
},
|
||||
somehow,
|
||||
|
|
@ -28,3 +33,74 @@ pub async fn get_graph(
|
|||
base,
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryGraphData {
|
||||
metric: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GraphData {
|
||||
hashes: Vec<String>,
|
||||
times: Vec<i64>,
|
||||
metrics: HashMap<String, Vec<Option<f64>>>,
|
||||
}
|
||||
|
||||
pub async fn get_graph_data(
|
||||
_path: PathGraphData,
|
||||
State(db): State<SqlitePool>,
|
||||
Query(form): Query<QueryGraphData>,
|
||||
) -> somehow::Result<impl IntoResponse> {
|
||||
let mut tx = db.begin().await?;
|
||||
let conn = tx.acquire().await?;
|
||||
|
||||
let rows = sqlx::query!(
|
||||
"\
|
||||
SELECT \
|
||||
hash, \
|
||||
committer_date AS \"committer_date: time::OffsetDateTime\" \
|
||||
FROM commits \
|
||||
ORDER BY committer_date ASC, hash ASC \
|
||||
"
|
||||
)
|
||||
.fetch_all(&mut *conn)
|
||||
.await?;
|
||||
|
||||
let mut hashes = Vec::with_capacity(rows.len());
|
||||
let mut times = Vec::with_capacity(rows.len());
|
||||
for row in rows {
|
||||
hashes.push(row.hash);
|
||||
times.push(row.committer_date.unix_timestamp());
|
||||
}
|
||||
|
||||
let mut metrics = HashMap::new();
|
||||
for metric in form.metric {
|
||||
let values = sqlx::query_scalar!(
|
||||
"\
|
||||
WITH \
|
||||
measurements AS ( \
|
||||
SELECT hash, value, MAX(start) \
|
||||
FROM runs \
|
||||
JOIN run_measurements USING (id) \
|
||||
WHERE name = ? \
|
||||
GROUP BY hash \
|
||||
) \
|
||||
SELECT value \
|
||||
FROM commits \
|
||||
LEFT JOIN measurements USING (hash) \
|
||||
ORDER BY committer_date ASC, hash ASC \
|
||||
",
|
||||
metric,
|
||||
)
|
||||
.fetch_all(&mut *conn)
|
||||
.await?;
|
||||
|
||||
metrics.insert(metric, values);
|
||||
}
|
||||
|
||||
Ok(Json(GraphData {
|
||||
hashes,
|
||||
times,
|
||||
metrics,
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ pub struct PathIndex {}
|
|||
#[typed_path("/graph/")]
|
||||
pub struct PathGraph {}
|
||||
|
||||
#[derive(Deserialize, TypedPath)]
|
||||
#[typed_path("/graph/data")]
|
||||
pub struct PathGraphData {}
|
||||
|
||||
#[derive(Deserialize, TypedPath)]
|
||||
#[typed_path("/queue/")]
|
||||
pub struct PathQueue {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue