A PLC Mirror written in Rust
at main 75 lines 1.9 kB view raw
1use deadpool_postgres::{Manager, Object, Pool}; 2use dropshot::{ApiDescription, ConfigLogging, ConfigLoggingLevel, HttpError}; 3use eyre::Context; 4use slog::Logger; 5use std::env::var; 6use std::str::FromStr; 7use tokio_postgres::{Config, NoTls}; 8 9mod api; 10mod db; 11pub mod import; 12mod types; 13mod utils; 14 15#[derive(Clone)] 16pub struct ApiContext { 17 pub pool: Pool, 18} 19 20impl ApiContext { 21 pub async fn get_conn(&self) -> Result<Object, HttpError> { 22 self.pool 23 .get() 24 .await 25 .map_err(|err| HttpError::for_internal_error(err.to_string())) 26 } 27} 28 29pub fn create_logger() -> eyre::Result<Logger> { 30 let log = ConfigLogging::StderrTerminal { 31 level: ConfigLoggingLevel::Info, 32 } 33 .to_logger("plc-mirror")?; 34 35 Ok(log) 36} 37 38pub fn create_api() -> eyre::Result<ApiDescription<ApiContext>> { 39 let mut api_desc = ApiDescription::new(); 40 41 api_desc.register(api::get_plc_op_log)?; 42 api_desc.register(api::get_plc_audit_log)?; 43 api_desc.register(api::get_last_op)?; 44 api_desc.register(api::resolve_did)?; 45 api_desc.register(api::index)?; 46 47 Ok(api_desc) 48} 49 50pub async fn connect_db() -> eyre::Result<Pool> { 51 let db_uri = var("PLC_DB_URI").wrap_err("PLC_DB_URI missing")?; 52 53 let cfg = Config::from_str(&db_uri)?; 54 let mgr = Manager::from_config(cfg, NoTls, Default::default()); 55 let pool = Pool::builder(mgr).build()?; 56 57 // run the init script 58 let init_conn = pool.get().await?; 59 init_conn.simple_query(include_str!("sql/init.sql")).await?; 60 61 Ok(pool) 62} 63 64pub async fn get_start_after(pool: &Pool) -> eyre::Result<Option<String>> { 65 if let Some(env_start_after) = var("PLC_START_AFTER").ok() { 66 return Ok(Some(env_start_after)); 67 } 68 69 let obj = pool.get().await?; 70 let last_ts = db::get_last_operation_ts(&obj) 71 .await? 72 .map(|v| v.to_rfc3339_opts(chrono::SecondsFormat::Millis, true)); 73 74 Ok(last_ts) 75}