From 9f6381071e8500f7ee7ff565bdb3cd3ac3a9606a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 28 Feb 2023 21:18:55 +0100 Subject: [PATCH] Use optimistic locking in Redis Fixes #2. --- src/routes/board.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/routes/board.rs b/src/routes/board.rs index 904b1c3..ebddb53 100644 --- a/src/routes/board.rs +++ b/src/routes/board.rs @@ -64,7 +64,7 @@ async fn ensure_key_is_empty(rconn: &mut redis::aio::Connection, key: &str) -> R .map_err(outcome::redis_cmd_failed)? .eq("none") .then_some(()) - .ok_or((StatusCode::CONFLICT, outcome::req_error!("Board already exists"))) + .ok_or_else(|| (StatusCode::CONFLICT, outcome::req_error!("Board already exists"))) } /// Handler for `GET /board/`. @@ -140,16 +140,19 @@ pub(crate) async fn route_board_post( let mut rconn = rclient.get_connection_or_504().await?; + log::trace!("Watching board keys..."); + redis::cmd("WATCH").arg(&order_key).arg(&token_key).arg(&scores_key).query_async(&mut rconn).await + .map_err(outcome::redis_cmd_failed)?; + log::trace!("Ensuring a board does not already exist..."); + ensure_key_is_empty(&mut rconn, &order_key).await?; + ensure_key_is_empty(&mut rconn, &token_key).await?; + ensure_key_is_empty(&mut rconn, &scores_key).await?; log::trace!("Starting Redis transaction..."); redis::cmd("MULTI").query_async(&mut rconn).await .map_err(outcome::redis_cmd_failed)?; - ensure_key_is_empty(&mut rconn, &order_key).await?; - ensure_key_is_empty(&mut rconn, &token_key).await?; - ensure_key_is_empty(&mut rconn, &scores_key).await?; - let token = SecureToken::new_or_500()?; log::debug!("Creating board: {name:?}");