Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7f2e5c2

Browse filesBrowse files
authored
Santi dashboard snapshots fix2 (#554)
1 parent 4d28952 commit 7f2e5c2
Copy full SHA for 7f2e5c2

File tree

Expand file treeCollapse file tree

9 files changed

+101
-72
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+101
-72
lines changed

‎pgml-dashboard/.gitignore

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.idea
2+
test_table.sql

‎pgml-dashboard/src/guards.rs

Copy file name to clipboardExpand all lines: pgml-dashboard/src/guards.rs
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ impl<'r> FromRequest<'r> for Cluster {
4949
None => return Outcome::Failure((Status::BadRequest, ())),
5050
};
5151

52-
Outcome::Success(Cluster { pool, context: shared_state.get_context(cluster_id) })
52+
Outcome::Success(Cluster {
53+
pool,
54+
context: shared_state.get_context(cluster_id),
55+
})
5356
}
5457
}
5558

‎pgml-dashboard/src/lib.rs

Copy file name to clipboardExpand all lines: pgml-dashboard/src/lib.rs
+9-13Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use sqlx::Executor;
3131
#[derive(Debug, Default, Clone)]
3232
pub struct Context {
3333
pub user: models::User,
34-
pub cluster: models::Cluster,
34+
pub cluster: models::Cluster,
3535
}
3636

3737
/// Globally shared state, saved in memory.
@@ -51,10 +51,13 @@ impl Clusters {
5151
.max_connections(5)
5252
.idle_timeout(std::time::Duration::from_millis(15_000))
5353
.min_connections(0)
54-
.after_connect(|conn, _meta| Box::pin(async move {
55-
conn.execute("SET application_name = 'pgml_dashboard';").await?;
56-
Ok(())
57-
}))
54+
.after_connect(|conn, _meta| {
55+
Box::pin(async move {
56+
conn.execute("SET application_name = 'pgml_dashboard';")
57+
.await?;
58+
Ok(())
59+
})
60+
})
5861
.connect_lazy(database_url)?;
5962

6063
pools.insert(cluster_id, pool.clone());
@@ -417,18 +420,11 @@ pub async fn models_get(cluster: Cluster, id: i64) -> Result<ResponseOk, errors:
417420
#[get("/snapshots")]
418421
pub async fn snapshots_index(cluster: Cluster) -> Result<ResponseOk, errors::Error> {
419422
let snapshots = models::Snapshot::all(cluster.pool()).await?;
420-
let mut table_sizes = HashMap::new();
421-
422-
for snapshot in &snapshots {
423-
let table_size = snapshot.table_size(cluster.pool()).await?;
424-
table_sizes.insert(snapshot.id, table_size);
425-
}
426423

427424
Ok(ResponseOk(
428425
templates::Snapshots {
429426
topic: "snapshots".to_string(),
430427
snapshots,
431-
table_sizes,
432428
context: cluster.context.clone(),
433429
}
434430
.render_once()
@@ -440,6 +436,7 @@ pub async fn snapshots_index(cluster: Cluster) -> Result<ResponseOk, errors::Err
440436
pub async fn snapshots_get(cluster: Cluster, id: i64) -> Result<ResponseOk, errors::Error> {
441437
let snapshot = models::Snapshot::get_by_id(cluster.pool(), id).await?;
442438
let samples = snapshot.samples(cluster.pool(), 500).await?;
439+
443440
let models = snapshot.models(cluster.pool()).await?;
444441
let mut projects = HashMap::new();
445442

@@ -450,7 +447,6 @@ pub async fn snapshots_get(cluster: Cluster, id: i64) -> Result<ResponseOk, erro
450447
Ok(ResponseOk(
451448
templates::Snapshot {
452449
topic: "snapshots".to_string(),
453-
table_size: snapshot.table_size(cluster.pool()).await?,
454450
snapshot,
455451
models,
456452
projects,

‎pgml-dashboard/src/main.rs

Copy file name to clipboardExpand all lines: pgml-dashboard/src/main.rs
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ async fn main() {
1313
.add(-1, &pgml_dashboard::guards::default_database_url())
1414
.unwrap();
1515

16-
pgml_dashboard::migrate(&clusters.get(-1).unwrap()).await.unwrap();
16+
pgml_dashboard::migrate(&clusters.get(-1).unwrap())
17+
.await
18+
.unwrap();
1719

1820
let _ = rocket::build()
1921
.manage(clusters)

‎pgml-dashboard/src/models.rs

Copy file name to clipboardExpand all lines: pgml-dashboard/src/models.rs
+74-50Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Markdown
22
use comrak::{markdown_to_html, ComrakExtensionOptions, ComrakOptions};
33

4+
use rocket::futures::TryFutureExt;
45
// Templates
56
use sailfish::TemplateOnce;
67

8+
use sqlx::postgres::PgRow;
79
// Database
810
use sqlx::postgres::types::PgInterval;
911
use sqlx::types::time::PrimitiveDateTime;
@@ -17,6 +19,7 @@ use tokio::io::{AsyncBufReadExt, AsyncSeekExt};
1719

1820
use crate::templates;
1921
use std::collections::HashMap;
22+
use std::str::FromStr;
2023

2124
#[derive(FromRow, Debug, Clone)]
2225
pub struct Project {
@@ -533,6 +536,8 @@ pub struct Snapshot {
533536
pub analysis: Option<serde_json::Value>,
534537
pub created_at: PrimitiveDateTime,
535538
pub updated_at: PrimitiveDateTime,
539+
pub exists: bool,
540+
pub table_size: String,
536541
}
537542

538543
impl Snapshot {
@@ -548,8 +553,22 @@ impl Snapshot {
548553
columns,
549554
analysis,
550555
created_at,
551-
updated_at
552-
FROM pgml.snapshots JOIN pg_class ON oid::regclass::text = relation_name"
556+
updated_at,
557+
CASE
558+
WHEN EXISTS (
559+
SELECT 1
560+
FROM pg_class c
561+
WHERE c.oid::regclass::text = relation_name
562+
) THEN pg_size_pretty(pg_total_relation_size(relation_name::regclass))
563+
ELSE '0 Bytes'
564+
END AS \"table_size!\",
565+
EXISTS (
566+
SELECT 1
567+
FROM pg_class c
568+
WHERE c.oid::regclass::text = relation_name
569+
) AS \"exists!\"
570+
FROM pgml.snapshots
571+
"
553572
)
554573
.fetch_all(pool)
555574
.await?)
@@ -566,25 +585,27 @@ impl Snapshot {
566585
columns,
567586
analysis,
568587
created_at,
569-
updated_at
570-
FROM pgml.snapshots JOIN pg_class ON oid::regclass::text = relation_name
571-
WHERE id = $1",
588+
updated_at,
589+
CASE
590+
WHEN EXISTS (
591+
SELECT 1
592+
FROM pg_class c
593+
WHERE c.oid::regclass::text = relation_name
594+
) THEN pg_size_pretty(pg_total_relation_size(relation_name::regclass))
595+
ELSE '0 Bytes'
596+
END AS \"table_size!\",
597+
EXISTS (
598+
SELECT 1
599+
FROM pg_class c
600+
WHERE c.oid::regclass::text = relation_name
601+
) AS \"exists!\"
602+
FROM pgml.snapshots WHERE id = $1",
572603
id,
573604
)
574605
.fetch_one(pool)
575606
.await?)
576607
}
577608

578-
pub async fn table_size(&self, pool: &PgPool) -> anyhow::Result<String> {
579-
let row =
580-
sqlx::query("SELECT pg_size_pretty(pg_total_relation_size($1))::TEXT AS table_size")
581-
.bind(&self.relation_name)
582-
.fetch_one(pool)
583-
.await?;
584-
585-
Ok(row.try_get("table_size")?)
586-
}
587-
588609
pub fn rows(&self) -> Option<i64> {
589610
match self.analysis.as_ref() {
590611
Some(analysis) => match analysis.get("samples") {
@@ -600,26 +621,28 @@ impl Snapshot {
600621
pool: &PgPool,
601622
rows: i64,
602623
) -> anyhow::Result<HashMap<String, Vec<f32>>> {
603-
let rows = sqlx::query(&format!(
604-
"SELECT row_to_json(row) r
605-
FROM (SELECT * FROM {} LIMIT $1) row",
606-
self.relation_name
607-
))
608-
.bind(rows)
609-
.fetch_all(pool)
610-
.await?;
611-
612624
let mut samples = HashMap::new();
613625

614-
rows.iter().for_each(|row| {
615-
let r: serde_json::Value = row.try_get("r").unwrap();
616-
let obj = r.as_object().unwrap();
626+
if self.exists {
627+
let rows = sqlx::query(&format!(
628+
"SELECT row_to_json(row) r
629+
FROM (SELECT * FROM {} LIMIT $1) row",
630+
self.relation_name
631+
))
632+
.bind(rows)
633+
.fetch_all(pool)
634+
.await?;
617635

618-
for (key, value) in obj.iter() {
619-
let rf = samples.entry(key.clone()).or_insert(Vec::new());
620-
rf.push(value.as_f64().unwrap_or(0.) as f32);
621-
}
622-
});
636+
rows.iter().for_each(|row| {
637+
let r: serde_json::Value = row.try_get("r").unwrap();
638+
let obj = r.as_object().unwrap();
639+
640+
for (key, value) in obj.iter() {
641+
let rf = samples.entry(key.clone()).or_insert(Vec::new());
642+
rf.push(value.as_f64().unwrap_or(0.) as f32);
643+
}
644+
});
645+
}
623646

624647
Ok(samples)
625648
}
@@ -664,48 +687,49 @@ impl Snapshot {
664687
}
665688

666689
pub fn labels<'a>(&'a self) -> Option<Vec<&'a serde_json::Map<String, serde_json::Value>>> {
667-
self.columns().map(|columns|
690+
self.columns().map(|columns| {
668691
columns
669692
.into_iter()
670693
.filter(|column| {
671694
self.y_column_name
672695
.contains(&column["name"].as_str().unwrap().to_string())
673696
})
674697
.collect()
675-
)
698+
})
676699
}
677700

678701
pub async fn models(&self, pool: &PgPool) -> anyhow::Result<Vec<Model>> {
679702
Model::get_by_snapshot_id(pool, self.id).await
680703
}
681704

682705
pub fn target_stddev(&self, name: &str) -> f32 {
683-
match self.analysis
706+
match self
707+
.analysis
684708
.as_ref()
685709
.unwrap()
686710
.as_object()
687711
.unwrap()
688-
.get(&format!("{}_stddev", name)) {
712+
.get(&format!("{}_stddev", name))
713+
{
689714
// 2.1
690715
Some(value) => value.as_f64().unwrap() as f32,
691716
// 2.2+
692717
None => {
693718
let columns = self.columns().unwrap();
694-
let column = columns.iter().find(|column|
695-
&column["name"].as_str().unwrap() == &name
696-
);
719+
let column = columns
720+
.iter()
721+
.find(|column| &column["name"].as_str().unwrap() == &name);
697722
match column {
698-
Some(column) => {
699-
column.get("statistics")
700-
.unwrap()
701-
.as_object()
702-
.unwrap()
703-
.get("std_dev")
704-
.unwrap()
705-
.as_f64()
706-
.unwrap() as f32
707-
},
708-
None => 0.
723+
Some(column) => column
724+
.get("statistics")
725+
.unwrap()
726+
.as_object()
727+
.unwrap()
728+
.get("std_dev")
729+
.unwrap()
730+
.as_f64()
731+
.unwrap() as f32,
732+
None => 0.,
709733
}
710734
}
711735
}

‎pgml-dashboard/src/templates.rs

Copy file name to clipboardExpand all lines: pgml-dashboard/src/templates.rs
-2Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ pub struct Model {
231231
pub struct Snapshots {
232232
pub topic: String,
233233
pub snapshots: Vec<models::Snapshot>,
234-
pub table_sizes: HashMap<i64, String>,
235234
pub context: Context,
236235
}
237236

@@ -242,7 +241,6 @@ pub struct Snapshot {
242241
pub snapshot: models::Snapshot,
243242
pub models: Vec<models::Model>,
244243
pub projects: HashMap<i64, models::Project>,
245-
pub table_size: String,
246244
pub samples: HashMap<String, Vec<f32>>,
247245
pub context: Context,
248246
}

‎pgml-dashboard/templates/model.html

Copy file name to clipboardExpand all lines: pgml-dashboard/templates/model.html
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ <h1><span class="material-symbols-outlined">model_training</span><%= model.algor
1212
<dl>
1313
<dt>Project</dt>
1414
<dd><a href="/dashboard/projects/<%= project.id %>"><%= project.name %></a></dd>
15-
<dt>Snapshot</dt>
16-
<dd><a href="/dashboard/snapshots/<%= snapshot.id %>"><%= snapshot.relation_name %></a></dd>
15+
<dt>Snapshot</dt>
16+
<dd><a href="/dashboard/snapshots/<%= snapshot.id %>"><%= snapshot.relation_name %></a></dd>
1717
<dt>Created</dt>
1818
<dd><time datetime="<% model.created_at; %>"><% model.created_at; %></time></dd>
1919
</dl>

‎pgml-dashboard/templates/snapshot.html

Copy file name to clipboardExpand all lines: pgml-dashboard/templates/snapshot.html
+7-2Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ <h1><span class="material-symbols-outlined">storage</span><%= snapshot.relation_
1313
<dt>Snapshot ID</dt>
1414
<dd><%= snapshot.id %></dd>
1515
<dt>Table Size</dt>
16-
<dd><%= table_size %></dd>
16+
<dd><%= snapshot.table_size %></dd>
1717
<dt>Rows</dt>
1818
<dd><%= snapshot.rows().unwrap() %></dd>
1919
<dt>Features</dt>
@@ -61,6 +61,7 @@ <h2><span class="material-symbols-outlined">model_training</span>Models</h2>
6161
</section>
6262
<% } %>
6363

64+
<% if snapshot.exists { %>
6465
<section>
6566
<h2><span class="material-symbols-outlined">label_important</span>Labels</h2>
6667
<% for label in snapshot.labels().unwrap().iter() {
@@ -131,5 +132,9 @@ <h3><%= name %>&nbsp;<code><%= feature["pg_type"].as_str().unwrap() | upper %></
131132
}
132133
renderCharts();
133134
</script>
134-
135+
<%} else { %>
136+
<section>
137+
<p style="color: gray"> <center> Data no longer exists to plot statistics </center></p>
138+
</section>
139+
<% }%>
135140
<% include!("footer.html"); %>

‎pgml-dashboard/templates/snapshots.html

Copy file name to clipboardExpand all lines: pgml-dashboard/templates/snapshots.html
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ <h1><span class="material-symbols-outlined">storage</span>Snapshots</h1>
77
<li>
88
<a href="/dashboard/snapshots/<%= snapshot.id %>">
99
<span><%= snapshot.relation_name %> </span>
10-
<span><%= table_sizes[&snapshot.id] %></span>
10+
<span><%= snapshot.table_size %></span>
1111
<span><time datetime="<% snapshot.created_at; %>"><% snapshot.created_at; %></time></span>
1212
</a>
1313
</li>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.