rex_db/
lib.rs

1pub mod models;
2mod schema;
3
4use anyhow::{Result, anyhow};
5use diesel::prelude::*;
6use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
7use std::collections::{HashMap, HashSet};
8
9use crate::models::{FullTx, Tag, TxMethod};
10
11pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("src/migrations");
12
13pub trait ConnCache {
14    fn conn(&mut self) -> &mut SqliteConnection;
15    fn cache(&self) -> &Cache;
16}
17
18#[derive(Clone)]
19pub struct Cache {
20    pub tags: HashMap<i32, Tag>,
21    pub tx_methods: HashMap<i32, TxMethod>,
22    pub txs: Option<HashMap<i32, Vec<FullTx>>>,
23    pub details: HashSet<String>,
24}
25
26impl Cache {
27    pub fn get_method_id(&self, name: &str) -> Result<i32> {
28        self.tx_methods
29            .values()
30            .find(|m| m.name == name)
31            .map(|m| m.id)
32            .ok_or_else(|| anyhow!("method '{name}' not found"))
33    }
34
35    pub fn get_method_by_name(&self, name: &str) -> Result<&TxMethod> {
36        self.tx_methods
37            .values()
38            .find(|m| m.name == name)
39            .ok_or_else(|| anyhow!("method '{name}' not found"))
40    }
41
42    pub fn get_method_by_name_mut(&mut self, name: &str) -> Result<&mut TxMethod> {
43        let method = self.get_method_by_name(name)?.id;
44
45        Ok(self.tx_methods.get_mut(&method).unwrap())
46    }
47
48    pub fn get_tag_id(&self, name: &str) -> Result<i32> {
49        self.tags
50            .values()
51            .find(|m| m.name == name)
52            .map(|m| m.id)
53            .ok_or_else(|| anyhow!("tag '{name}' not found"))
54    }
55
56    pub fn new_tags(&mut self, tags: Vec<Tag>) {
57        for tag in tags {
58            self.tags.insert(tag.id, tag);
59        }
60    }
61
62    pub fn new_tx_methods(&mut self, tx_methods: Vec<TxMethod>) {
63        for tx_method in tx_methods {
64            self.tx_methods.insert(tx_method.id, tx_method);
65        }
66    }
67
68    // TODO: Start using cache
69    pub fn set_txs(&mut self, txs: HashMap<i32, Vec<FullTx>>) {
70        self.txs = Some(txs);
71    }
72
73    #[must_use]
74    pub fn get_txs(&self, id: i32) -> Option<&Vec<FullTx>> {
75        if let Some(txs) = &self.txs {
76            return txs.get(&id);
77        }
78
79        None
80    }
81
82    #[must_use]
83    pub fn get_methods(&self) -> Vec<&TxMethod> {
84        let mut methods = self.tx_methods.values().collect::<Vec<&TxMethod>>();
85        methods.sort_by_key(|value| value.position);
86        methods
87    }
88
89    #[must_use]
90    pub fn get_tags_set(&self) -> HashSet<String> {
91        self.tags
92            .values()
93            .map(|m| m.name.clone())
94            .collect::<HashSet<String>>()
95    }
96
97    #[must_use]
98    pub fn get_tags_sorted(&self) -> Vec<&Tag> {
99        let mut tags = self.tags.values().collect::<Vec<&Tag>>();
100        tags.sort_by_key(|value| &value.name);
101        tags
102    }
103}
104
105#[must_use]
106pub fn get_connection(db_url: &str) -> SqliteConnection {
107    let mut conn =
108        SqliteConnection::establish(db_url).expect("Failed to create connection to database");
109
110    conn.run_pending_migrations(MIGRATIONS)
111        .expect("Failed to run database migrations");
112
113    diesel::sql_query("PRAGMA foreign_keys = ON;")
114        .execute(&mut conn)
115        .unwrap();
116
117    conn
118}
119
120#[must_use]
121pub fn get_connection_no_migrations(db_url: &str) -> SqliteConnection {
122    let mut conn =
123        SqliteConnection::establish(db_url).expect("Failed to create connection to database");
124
125    diesel::sql_query("PRAGMA foreign_keys = ON;")
126        .execute(&mut conn)
127        .unwrap();
128
129    conn
130}