From 794e1de9e2a35bdc855cb23dda59f73a5eb603d5 Mon Sep 17 00:00:00 2001 From: emilielr Date: Tue, 27 Aug 2024 15:38:26 +0200 Subject: [PATCH 1/5] feat(backend): endpoint for updating single board --- backend/Cargo.toml | 2 +- backend/src/main.rs | 36 +++++++++++++++++++++++++++++------- backend/src/types.rs | 36 +++++++++++++++++++++++++++++++++--- backend/src/utils.rs | 1 + 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 58ce0d99c..a243de1d9 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0.86" axum = {version = "0.7.4", features = ["ws", "macros"]} axum-auth = { version = "0.7.0", default-features= false, features = ["auth-bearer"] } futures-util = "0.3.30" -redis = {version = "0.25.3", features = ["tokio-comp", "aio"]} +redis = {version = "0.26.1", features = ["tokio-comp", "aio", "json"]} serde = {version = "1.0.199", features = ["derive"]} serde_json = "1.0.116" tokio = { version = "1.36.0", features = ["macros", "rt","rt-multi-thread", "signal"] } diff --git a/backend/src/main.rs b/backend/src/main.rs index 67eff08a5..7de488416 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -9,7 +9,7 @@ use axum::{ }; use axum_auth::AuthBearer; -use serde_json::{from_str, Value}; +use serde_json::{to_string, Value}; use tokio::{net::TcpListener, time}; use redis::{AsyncCommands, ConnectionLike}; @@ -21,7 +21,7 @@ mod types; mod utils; use tower_http::cors::CorsLayer; -use types::{AppError, AppState, Message}; +use types::{AppError, AppState, BoardAction, Message}; use utils::{graceful_shutdown, setup_redis}; use crate::types::Guard; @@ -61,6 +61,7 @@ async fn main() { .route("/subscribe/:bid", get(subscribe)) .route("/refresh/:bid", post(trigger)) .route("/update", post(update)) + .route("/update/:bid", post(update_board)) .route("/alive", get(check_health)) .route("/reset", post(reset_active)) .with_state(redis_clients) @@ -115,7 +116,10 @@ async fn trigger( if token != state.key { return Ok(StatusCode::UNAUTHORIZED); } - state.master.publish(bid, payload.to_string()).await?; + state + .master + .publish(bid, BoardAction::Refresh { payload: payload }) + .await?; Ok(StatusCode::OK) } @@ -130,6 +134,21 @@ async fn update( Ok(StatusCode::OK) } +async fn update_board( + AuthBearer(token): AuthBearer, + State(mut state): State, + Path(bid): Path, +) -> Result { + if token != state.key { + return Ok(StatusCode::UNAUTHORIZED); + } + state + .master + .publish(bid, to_string(&BoardAction::Update)?) // "update" + .await?; + Ok(StatusCode::OK) +} + async fn subscribe( Path(bid): Path, State(state): State, @@ -147,11 +166,14 @@ async fn subscribe( if channel == "update" { Message::Update } else { - let payload = msg.get_payload::()?; - Message::Refresh { - payload: from_str::(payload.as_str())?, - }} + let payload = msg.get_payload::()?; + + match payload { + BoardAction::Refresh { payload } => Message::Refresh { payload: payload }, + BoardAction::Update => Message::Update, + } } + } () = time::sleep(Duration::from_secs(55)) => { Message::Timeout } diff --git a/backend/src/types.rs b/backend/src/types.rs index e8c06709f..a3f1ea78c 100644 --- a/backend/src/types.rs +++ b/backend/src/types.rs @@ -3,8 +3,11 @@ use axum::{ http::{Response, StatusCode}, response::IntoResponse, }; -use redis::{aio::MultiplexedConnection, AsyncCommands, Client}; -use serde::Serialize; +use redis::{ + aio::MultiplexedConnection, from_redis_value, AsyncCommands, Client, FromRedisValue, + ToRedisArgs, +}; +use serde::{Deserialize, Serialize}; use serde_json::{to_string, Value}; #[derive(Clone)] @@ -22,6 +25,33 @@ pub enum Message { Timeout, } +#[derive(Serialize, Deserialize)] +pub enum BoardAction { + Refresh { payload: Value }, + Update, +} + +impl FromRedisValue for BoardAction { + fn from_redis_value(v: &redis::Value) -> redis::RedisResult { + let s: String = from_redis_value(v)?; + Ok(serde_json::from_str::(&s)?) + } +} + +impl ToRedisArgs for BoardAction { + fn write_redis_args(&self, out: &mut W) + where + W: ?Sized + redis::RedisWrite, + { + let s = serde_json::to_string(self); + + match s { + Ok(s) => out.write_arg_fmt(s), + Err(_) => out.write_arg_fmt(""), + } + } +} + pub struct Guard { pub master: MultiplexedConnection, } @@ -65,7 +95,7 @@ pub struct AppError { impl IntoResponse for AppError { fn into_response(self) -> axum::response::Response { - (StatusCode::INTERNAL_SERVER_ERROR).into_response() + StatusCode::INTERNAL_SERVER_ERROR.into_response() } } diff --git a/backend/src/utils.rs b/backend/src/utils.rs index e6c95f815..4e718a694 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -34,6 +34,7 @@ pub async fn setup_redis() -> (MultiplexedConnection, Client) { db: 0, username: None, password: Some(redis_pw), + protocol: redis::ProtocolVersion::RESP3, }; let master_host = std::env::var("REDIS_MASTER_SERVICE_HOST") From 455ac7416adc576851a9e7e1732f93c6e434c4d8 Mon Sep 17 00:00:00 2001 From: emilielr Date: Wed, 28 Aug 2024 09:49:32 +0200 Subject: [PATCH 2/5] chore(format): remove redundant field names --- backend/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main.rs b/backend/src/main.rs index 7de488416..ff821e3fa 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -118,7 +118,7 @@ async fn trigger( } state .master - .publish(bid, BoardAction::Refresh { payload: payload }) + .publish(bid, BoardAction::Refresh { payload }) .await?; Ok(StatusCode::OK) } @@ -169,7 +169,7 @@ async fn subscribe( let payload = msg.get_payload::()?; match payload { - BoardAction::Refresh { payload } => Message::Refresh { payload: payload }, + BoardAction::Refresh { payload } => Message::Refresh { payload }, BoardAction::Update => Message::Update, } } From f722eb68015af7ae15114ef801b72c3b68ea0af7 Mon Sep 17 00:00:00 2001 From: emilielr Date: Wed, 28 Aug 2024 09:55:29 +0200 Subject: [PATCH 3/5] chore(): remove comment --- backend/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main.rs b/backend/src/main.rs index ff821e3fa..f75b39d32 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -144,7 +144,7 @@ async fn update_board( } state .master - .publish(bid, to_string(&BoardAction::Update)?) // "update" + .publish(bid, to_string(&BoardAction::Update)?) .await?; Ok(StatusCode::OK) } From 2432bb4dce3781be5ad78c976f80c901c023cdec Mon Sep 17 00:00:00 2001 From: emilielr Date: Wed, 28 Aug 2024 10:32:04 +0200 Subject: [PATCH 4/5] refactor(update): change input on error --- backend/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/types.rs b/backend/src/types.rs index a3f1ea78c..ea9415c37 100644 --- a/backend/src/types.rs +++ b/backend/src/types.rs @@ -47,7 +47,7 @@ impl ToRedisArgs for BoardAction { match s { Ok(s) => out.write_arg_fmt(s), - Err(_) => out.write_arg_fmt(""), + Err(_) => out.write_arg_fmt(0_u8), } } } From 3e72acea2df604f7a85b0fa5ec453017acab7736 Mon Sep 17 00:00:00 2001 From: emilielr Date: Wed, 28 Aug 2024 14:57:13 +0200 Subject: [PATCH 5/5] refactor(update): simplify trait --- backend/src/types.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/types.rs b/backend/src/types.rs index ea9415c37..24d322600 100644 --- a/backend/src/types.rs +++ b/backend/src/types.rs @@ -43,9 +43,7 @@ impl ToRedisArgs for BoardAction { where W: ?Sized + redis::RedisWrite, { - let s = serde_json::to_string(self); - - match s { + match to_string(self) { Ok(s) => out.write_arg_fmt(s), Err(_) => out.write_arg_fmt(0_u8), }