From: Geoffrey Allott Date: Fri, 5 Feb 2021 17:06:31 +0000 (+0000) Subject: use redis::Script to handle script hash caching X-Git-Url: https://git.pointlesshacks.com/?a=commitdiff_plain;h=e429b37b2a53c18d9b0c0291d4ca011fbc81c473;p=pokerwave.git use redis::Script to handle script hash caching --- diff --git a/src/server.rs b/src/server.rs index 155c0c0..0e32637 100644 --- a/src/server.rs +++ b/src/server.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::convert::TryFrom; use futures::{channel::mpsc::{Receiver, Sender, channel}, SinkExt}; -use redis::{AsyncCommands, ErrorKind, FromRedisValue, Msg, RedisError, RedisResult, RedisWrite, ToRedisArgs, Value, aio::MultiplexedConnection}; +use redis::{AsyncCommands, ErrorKind, FromRedisValue, Msg, RedisError, RedisResult, RedisWrite, Script, ToRedisArgs, Value, aio::MultiplexedConnection}; use serde::{Serialize, Deserialize}; use crate::auth::Auth; @@ -69,6 +69,19 @@ impl ToRedisArgs for ClientInterest { } } +const TAKE_ACTION_LUA_SCRIPT: &'static str = r#" + local len = redis.call('llen', KEYS[1]) + local expected = tonumber(ARGV[1]) + if (len == expected) then + return redis.call('rpush', KEYS[1], ARGV[2]) + elseif (len > expected) then + return 0 + else + local error = string.format('Inconsistent game state - database reports %d actions but expected at least %d', len, expected) + return redis.error_reply(error) + end +"#; + impl Server { pub fn new(redis: MultiplexedConnection, register_update_stream: Sender) -> Self { Self { @@ -82,13 +95,15 @@ impl Server { if let Err(err) = self.register_update_stream.clone().send(client_interest_sender).await { error!("new_state: Send failed: {}", err); } - (ServerState{redis: self.redis.clone(), register_interest}, interest) + let take_action_script = Script::new(TAKE_ACTION_LUA_SCRIPT); + (ServerState{redis: self.redis.clone(), register_interest, take_action_script}, interest) } } pub struct ServerState { redis: MultiplexedConnection, register_interest: Sender>, + take_action_script: Script, } fn user_key(username: &str) -> String { @@ -99,19 +114,6 @@ fn game_key(id: u32) -> String { format!("game:{}", id) } -const TAKE_ACTION_LUA_SCRIPT: &'static str = r#" - local len = redis.call('llen', KEYS[1]) - local expected = tonumber(ARGV[1]) - if (len == expected) then - return redis.call('rpush', KEYS[1], ARGV[2]) - elseif (len > expected) then - return 0 - else - local error = string.format('Inconsistent game state - database reports %d actions but expected at least %d', len, expected) - return redis.error_reply(error) - end -"#; - impl ServerState { pub async fn create_user(&mut self, username: &str, auth: Auth, nickname: &str) -> RedisResult<()> { let key = user_key(username); @@ -182,8 +184,8 @@ impl ServerState { pub async fn take_action(&mut self, id: u32, len: usize, action: &UserAction) -> RedisResult { let key = game_key(id); - debug!("redis: executing: EVAL {:?} 1 {:?} {} {:?}", TAKE_ACTION_LUA_SCRIPT, key, len, serde_json::to_string(&action).unwrap()); - redis::cmd("EVAL").arg(TAKE_ACTION_LUA_SCRIPT).arg(1).arg(key).arg(len).arg(AsJson(action)).query_async(&mut self.redis).await + debug!("take_action: EVAL {{TAKE_ACTION_LUA_SCRIPT}} 1 {} {} {:?}", key, len, action); + self.take_action_script.key(key).arg(len).arg(AsJson(action)).invoke_async(&mut self.redis).await } pub async fn register_interests(&mut self, interests: HashSet) {