datadog_workflow_lib/database/
mod.rs

1pub mod models;
2pub mod monitors;
3pub mod screenboards;
4pub mod timeboards;
5
6use crate::database::models::Dashboard;
7use crate::database::monitors::Monitors;
8use crate::database::screenboards::Screenboards;
9use crate::database::timeboards::Timeboards;
10use failure::{format_err, Error};
11use rusqlite::{Connection, ToSql, NO_PARAMS};
12
13#[derive(Debug)]
14pub struct DbContext {
15    conn: Connection,
16    subdomain: String,
17}
18
19impl DbContext {
20    #[inline]
21    pub fn new(database_url: &str, subdomain: String) -> Result<Self, Error> {
22        let conn = Connection::open(&database_url)?;
23        Ok(DbContext { conn, subdomain })
24    }
25
26    // TODO: make interior mutable instead of everything having to be mutable
27
28    #[inline]
29    pub fn monitors(&mut self) -> Monitors {
30        Monitors::new(self)
31    }
32
33    #[inline]
34    pub fn timeboards(&mut self) -> Timeboards {
35        Timeboards::new(self)
36    }
37
38    #[inline]
39    pub fn screenboards(&mut self) -> Screenboards {
40        Screenboards::new(self)
41    }
42
43    #[inline]
44    pub fn find_dashboard(&self, title: &str, limit: i64) -> Result<Vec<Dashboard>, Error> {
45        // This will allow searching by full name or just the words within the name;
46        // it's not a regex but it's good enough.
47        let query = format!(
48            "%{}%",
49            title
50                .split_terminator(' ')
51                .flat_map(|s| s.split_terminator('_'))
52                .flat_map(|s| s.split_terminator('-'))
53                .collect::<Vec<&str>>()
54                .join("%")
55        );
56
57        self.conn.prepare(
58            "SELECT title, description, url, modified FROM timeboards WHERE title LIKE ?1
59                         UNION ALL
60                         SELECT title, description, url, modified FROM screenboards WHERE title LIKE ?1
61                         ORDER BY modified DESC
62                         LIMIT ?",
63        )?.query_map(&[&query as &dyn ToSql,&limit], |row| {
64            Ok(Dashboard{
65                title:row.get(0)?,
66                description:row.get(1)?,
67                url: row.get(2)?,
68            })
69        })?.map(|r|{
70            match r{
71                Ok(v) => Ok(v),
72                Err(e)=> Err(format_err!("Query + Transform into ScreenBoard failed: {}",e)),
73            }
74        }).collect::<Result<Vec<_>, _>>()
75    }
76
77    #[inline]
78    pub fn run_migrations(&mut self) -> Result<(), Error> {
79        self.timeboards().run_migrations()?;
80        self.screenboards().run_migrations()?;
81        self.monitors().run_migrations()?;
82        Ok(())
83    }
84
85    #[inline]
86    pub fn optimize(&self) -> Result<(), Error> {
87        // since this workflow is READ heavy, let's optimize the SQLite indexes and DB
88        self.conn.execute("VACUUM;", NO_PARAMS)?;
89        Ok(())
90    }
91}