//! Locker repository implementation for item data persistence operations. //! //! This module provides the data access layer for locker management. //! Each player's locker is stored as a single JSON string containing all their items. use forge_models::{Item, Locker}; use forge_shared::RedisClient; use std::collections::HashMap; /// Repository trait defining the contract for locker data operations. pub trait LockerRepository: Send + Sync { /// Creates a new locker for a player fn create(&self, uid: &str, locker: &Locker) -> Result<(), String>; /// Updates an existing locker with new item data fn update(&self, uid: &str, locker: &Locker) -> Result<(), String>; /// Retrieves a player's locker fn get(&self, uid: &str) -> Result, String>; /// Deletes a player's locker (all items) fn delete(&self, uid: &str) -> Result<(), String>; /// Checks if a player has a locker fn exists(&self, uid: &str) -> Result; } /// Redis-based implementation of the LockerRepository trait. /// /// Stores each player's locker as a single JSON string array with the key format `locker:{uid}`. pub struct RedisLockerRepository { client: C, } impl RedisLockerRepository { pub fn new(client: C) -> Self { Self { client } } } impl LockerRepository for RedisLockerRepository { fn create(&self, uid: &str, locker: &Locker) -> Result<(), String> { let redis_key = format!("locker:{}", uid); // Serialize just the items array let locker_json = serde_json::to_string(&locker.items) .map_err(|e| format!("Failed to serialize locker: {}", e))?; // Store as a simple string value self.client.set_key(redis_key, locker_json) } fn update(&self, uid: &str, locker: &Locker) -> Result<(), String> { let redis_key = format!("locker:{}", uid); // Serialize just the items array let locker_json = serde_json::to_string(&locker.items) .map_err(|e| format!("Failed to serialize locker: {}", e))?; // Update the existing locker self.client.set_key(redis_key, locker_json) } fn get(&self, uid: &str) -> Result, String> { let redis_key = format!("locker:{}", uid); // Get the JSON string from Redis let locker_string = self.client.get_key(redis_key)?; // Return None if no data found if locker_string.is_empty() { return Ok(None); } // Deserialize the items data match serde_json::from_str::>(&locker_string) { Ok(items) => Ok(Some(Locker { items })), Err(e) => Err(format!("Failed to deserialize locker: {}", e)), } } fn delete(&self, uid: &str) -> Result<(), String> { let redis_key = format!("locker:{}", uid); self.client.delete_key(redis_key) } fn exists(&self, uid: &str) -> Result { let redis_key = format!("locker:{}", uid); self.client.key_exists(redis_key) } }