Add a leaderboard with Redis
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
abf902c80e
commit
429fed7893
@ -0,0 +1,62 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use redis::{AsyncCommands, RedisError};
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
const LEADERBOARD: &str = "leaderboard";
|
||||||
|
type LeaderboardEntry = (String, i32);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
trait Leaderboard {
|
||||||
|
async fn add_score(&self, player_name: &str, score: i32) -> Result<(), RedisError>;
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RedisLeaderboard {
|
||||||
|
client: redis::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RedisLeaderboard {
|
||||||
|
fn new(client: redis::Client) -> Self {
|
||||||
|
Self { client }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Leaderboard for RedisLeaderboard {
|
||||||
|
async fn add_score(&self, player_name: &str, score: i32) -> Result<(), RedisError> {
|
||||||
|
let mut con = self.client.get_async_connection().await?;
|
||||||
|
con.zadd(LEADERBOARD, player_name, score).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError> {
|
||||||
|
let mut con = self.client.get_async_connection().await?;
|
||||||
|
let count: isize = con.zcard(LEADERBOARD).await?;
|
||||||
|
let leaderboard: Vec<LeaderboardEntry> =
|
||||||
|
con.zrange_withscores(LEADERBOARD, 0, count - 1).await?;
|
||||||
|
Ok(leaderboard)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InMemoryLeaderboard();
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Leaderboard for InMemoryLeaderboard {
|
||||||
|
async fn add_score(&self, _: &str, _: i32) -> Result<(), RedisError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError> {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn provide_leaderboard() -> Box<dyn Leaderboard> {
|
||||||
|
match env::var("REDIS_HOSTNAME") {
|
||||||
|
Ok(redis_host_name) => match redis::Client::open(format!("redis://{redis_host_name}/")) {
|
||||||
|
Ok(client) => Box::new(RedisLeaderboard::new(client)),
|
||||||
|
Err(_) => Box::new(InMemoryLeaderboard()),
|
||||||
|
},
|
||||||
|
Err(_) => Box::new(InMemoryLeaderboard()),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue