Skip to main content

rbp_database/
check.rs

1use super::*;
2use rbp_cards::*;
3use std::sync::Arc;
4use tokio_postgres::Client;
5
6/// Check defines status queries for training orchestration.
7/// Consolidates existence/count checks used by Trainer and PreTraining.
8#[async_trait::async_trait]
9pub trait Check: Send + Sync {
10    async fn epochs(&self) -> usize;
11    async fn blueprint(&self) -> usize;
12    async fn clustered(&self, street: Street) -> bool;
13    async fn status(&self) {
14        fn commas(n: usize) -> String {
15            n.to_string()
16                .as_bytes()
17                .rchunks(3)
18                .rev()
19                .map(std::str::from_utf8)
20                .map(Result::unwrap)
21                .collect::<Vec<_>>()
22                .join(",")
23        }
24        log::info!("┌────────────┬───────────────┐");
25        log::info!("│ Street     │ Clustered     │");
26        log::info!("├────────────┼───────────────┤");
27        for street in Street::all().iter().rev().cloned() {
28            let done = self.clustered(street).await;
29            let mark = if done { "✓" } else { " " };
30            log::info!(
31                "│ {:?}{} │       {}       │",
32                street,
33                " ".repeat(10 - format!("{:?}", street).len()),
34                mark
35            );
36        }
37        log::info!("├────────────┼───────────────┤");
38        log::info!("│ Epoch      │ {:>13} │", commas(self.epochs().await));
39        log::info!("│ Blueprint  │ {:>13} │", commas(self.blueprint().await));
40        log::info!("└────────────┴───────────────┘");
41    }
42}
43
44#[async_trait::async_trait]
45impl Check for Client {
46    async fn epochs(&self) -> usize {
47        let sql = format!("SELECT value FROM {t} WHERE key = 'current'", t = EPOCH);
48        self.query_opt(&sql, &[])
49            .await
50            .ok()
51            .flatten()
52            .map(|r| r.get::<_, i64>(0) as usize)
53            .unwrap_or(0)
54    }
55    async fn blueprint(&self) -> usize {
56        let sql = format!("SELECT COUNT(*) FROM {t}", t = BLUEPRINT);
57        self.query_opt(&sql, &[])
58            .await
59            .ok()
60            .flatten()
61            .map(|r| r.get::<_, i64>(0) as usize)
62            .unwrap_or(0)
63    }
64    async fn clustered(&self, street: Street) -> bool {
65        let sql = format!("SELECT 1 FROM {t} WHERE obs = $1", t = ISOMORPHISM);
66        let obs = i64::from(Isomorphism::from(Observation::from(street)));
67        self.query_opt(&sql, &[&obs]).await.ok().flatten().is_some()
68    }
69}
70
71#[async_trait::async_trait]
72impl Check for Arc<Client> {
73    async fn epochs(&self) -> usize {
74        self.as_ref().epochs().await
75    }
76    async fn blueprint(&self) -> usize {
77        self.as_ref().blueprint().await
78    }
79    async fn clustered(&self, street: Street) -> bool {
80        self.as_ref().clustered(street).await
81    }
82}