summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Dybiec <pawel@dybiec.info>2024-11-11 22:56:20 +0000
committerPaweł Dybiec <pawel@dybiec.info>2024-11-11 22:56:20 +0000
commit2874e6f98abad8448bda5c4229293f1eb857b76c (patch)
tree2637a2c600f7f1c70688c036f1c81d348aa31d59
parentCleanup flake, update deps (diff)
Fix panic when closingmain
-rw-r--r--src/main.rs60
-rw-r--r--src/mattermost/client.rs10
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}");
}