diff options
author | Paweł Dybiec <pawel@dybiec.info> | 2024-11-11 22:56:20 +0000 |
---|---|---|
committer | Paweł Dybiec <pawel@dybiec.info> | 2024-11-11 22:56:20 +0000 |
commit | 2874e6f98abad8448bda5c4229293f1eb857b76c (patch) | |
tree | 2637a2c600f7f1c70688c036f1c81d348aa31d59 | |
parent | Cleanup flake, update deps (diff) |
Fix panic when closingmain
-rw-r--r-- | src/main.rs | 60 | ||||
-rw-r--r-- | src/mattermost/client.rs | 10 |
2 files changed, 36 insertions, 34 deletions
diff --git a/src/main.rs b/src/main.rs index 1dc8e63..86a07ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,26 +4,25 @@ use std::path::Path; use anyhow::anyhow; use tokio::signal::unix; use tokio::{self}; -use tracing::{debug, warn}; +use tracing::{instrument, warn}; struct Vav { - db_connection: Option<sqlite::ConnectionWithFullMutex>, + db_connection: sqlite::ConnectionWithFullMutex, } + impl Vav { - fn new<T: AsRef<Path>>(path: Option<T>) -> Self { + fn new<T: AsRef<Path>>(path: Option<T>) -> Option<Self> { let ret = Self { db_connection: path - .and_then(|path| sqlite::Connection::open_with_full_mutex(path).ok()), + .and_then(|path| sqlite::Connection::open_with_full_mutex(path).ok())?, }; - if let Some(connection) = &ret.db_connection { - let create_table_res = connection.execute( - "CREATE TABLE keyval (key text NOT NULL PRIMARY KEY, value text NOT NULL)", - ); - if let Err(err) = create_table_res { - warn!("Error while creating db {err}"); - } + let create_table_res = ret + .db_connection + .execute("CREATE TABLE keyval (key text NOT NULL PRIMARY KEY, value text NOT NULL)"); + if let Err(err) = create_table_res { + warn!("Error while creating db {err}"); } - ret + Some(ret) } } const INSERT_STATEMENT: &str = "INSERT INTO keyval (key,value) VALUES (?,?)"; @@ -31,13 +30,12 @@ const SELECT_ONE: &str = "SELECT key,value FROM keyval where key=?"; const SELECT_ALL: &str = "SELECT key,value FROM keyval"; #[async_trait::async_trait] impl mattermost::Handler for Vav { + #[instrument(skip(self, update))] async fn handle( &self, update: mattermost::model::WebsocketUpdate, client: &mattermost::Client, ) -> Result<(), anyhow::Error> { - debug!("as json: {update:?}"); - let posted = match update.update { mattermost::model::Update::Posted(posted) => posted, _ => return Ok(()), @@ -54,19 +52,17 @@ impl mattermost::Handler for Vav { let (name, value) = message .split_once(' ') .ok_or(anyhow::anyhow!("missing value in command store"))?; - if let Some(connection) = &self.db_connection { - let mut statement = connection.prepare(INSERT_STATEMENT)?; - statement.bind((1, name))?; - statement.bind((2, value))?; - if let Err(err) = statement.next() { - warn!("Error while writing to db {err}"); - } + let mut statement = self.db_connection.prepare(INSERT_STATEMENT)?; + statement.bind((1, name))?; + statement.bind((2, value))?; + if let Err(err) = statement.next() { + warn!("Error while writing to db {err}"); } } "lookup" => { let name = rest; - let response = if let Some(connection) = &self.db_connection { - let mut statement = connection.prepare(SELECT_ONE)?; + let response = { + let mut statement = self.db_connection.prepare(SELECT_ONE)?; statement.bind((1, name))?; match statement.next() { Ok(sqlite::State::Done) => "no entry under that name".to_owned(), @@ -76,14 +72,12 @@ impl mattermost::Handler for Vav { return Err(err.into()); } } - } else { - "uggh, no db".to_owned() }; client.reply_to(posted.post, response).await?; } "list" => { - let response = if let Some(connection) = &self.db_connection { - let mut statement = connection.prepare(SELECT_ALL)?; + let response = { + let mut statement = self.db_connection.prepare(SELECT_ALL)?; let mut res = vec!["Stored keys:".to_owned()]; while let Ok(result) = statement.next() { if result == sqlite::State::Done { @@ -92,8 +86,6 @@ impl mattermost::Handler for Vav { res.push(statement.read::<String, _>(0)?) } res.join("\n") - } else { - "uggh, no db".to_owned() }; client.reply_to(posted.post, response).await?; } @@ -109,17 +101,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let login = std::env::var("USER_MAIL")?; let password = std::env::var("USER_PASSWORD")?; let db = std::env::var("SQLITE_PATH").ok(); + let mm_url = std::env::var("MM_URL") + .unwrap_or("https://mattermost.continuum.ii.uni.wroc.pl".to_string()); let auth = mattermost::AuthData { login, password }; - let mut client = mattermost::Client::new(auth, "https://mattermost.continuum.ii.uni.wroc.pl"); + let mut client = mattermost::Client::new(auth, mm_url); client.update_bearer_token().await?; { let (shutdown_send, shutdown_recv) = tokio::sync::oneshot::channel(); let (on_task_finish_send, on_task_finish_recv) = tokio::sync::oneshot::channel(); let websocket_task = tokio::spawn(async move { let result = client - .handle_websocket_stream(Vav::new(db), shutdown_recv) + .handle_websocket_stream(Vav::new(db).expect("No db connection"), shutdown_recv) .await; - on_task_finish_send.send(result).unwrap(); + if let Err(result) = on_task_finish_send.send(result) { + warn!("Websocket task returned {:?}, but it couldn't be handled by main thread as it is closing", result); + } }); { let mut sigterm = unix::signal(unix::SignalKind::terminate())?; diff --git a/src/mattermost/client.rs b/src/mattermost/client.rs index 861e0a8..2172338 100644 --- a/src/mattermost/client.rs +++ b/src/mattermost/client.rs @@ -15,6 +15,11 @@ pub struct Client { bearer_token: Option<String>, client: reqwest::Client, } +impl std::fmt::Debug for Client { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Client").field("url", &self.url).finish() + } +} #[async_trait::async_trait] pub trait Handler { @@ -26,10 +31,10 @@ pub trait Handler { } impl Client { - pub(crate) fn new(auth: AuthData, url: &str) -> Self { + pub(crate) fn new(auth: AuthData, url: String) -> Self { Self { auth, - url: url.to_owned(), + url, bearer_token: None, client: reqwest::Client::new(), } @@ -90,6 +95,7 @@ impl Client { match json { Ok(websocketmessage) => { if let WebsocketMessage::Update(update) = websocketmessage { + debug!("Handling update {:?}", update); if let Err(err) = handler.handle(update, &self).await { warn!("Handler returned error: {err}"); } |