use crate::redis_cache::{Cache, RedisCache}; use serde::{Deserialize, Serialize}; use sqlx::Error; use sqlx::PgPool; use std::sync::Arc; #[derive(Debug, Serialize, Deserialize)] pub struct User { pub id: i32, pub username: String, pub email: String, pub hashed_password: String, pub roles: Vec, } pub struct UsersService { pub pool: PgPool, pub cache: Arc, // Shared Redis cache } impl UsersService { pub async fn create_user( &self, username: &str, email: &str, hashed_password: &str, ) -> Result { let result = sqlx::query!( r#" INSERT INTO users (username, email, hashed_password) VALUES ($1, $2, $3) RETURNING id "#, username, email, hashed_password ) .fetch_one(&self.pool) .await?; Ok(result.id) } pub async fn get_user_by_id(&self, user_id: i32) -> Result { // Check Redis cache first if let Ok(Some(cached_user)) = self.cache.get::(&format!("user:{}", user_id)).await { return Ok(cached_user); } // Fetch from PostgreSQL let row = sqlx::query!( "SELECT id, username, email, hashed_password, roles FROM users WHERE id = $1", user_id ) .fetch_one(&self.pool) .await?; let user = User { id: row.id, username: row.username, email: row.email, hashed_password: row.hashed_password, roles: row.roles.unwrap_or_default(), }; // Store result in Redis self.cache .set(&format!("user:{}", user_id), &user, 3600) .await .unwrap_or_else(|err| eprintln!("Failed to cache user: {:?}", err)); Ok(user) } pub async fn get_user_by_username(&self, username: &str) -> Result { // Check Redis cache first if let Ok(Some(cached_user)) = self.cache.get::(&format!("user_by_username:{}", username)).await { return Ok(cached_user); } // Fetch from PostgreSQL let row = sqlx::query!( "SELECT id, username, email, hashed_password, roles FROM users WHERE username = $1", username ) .fetch_one(&self.pool) .await?; let user = User { id: row.id, username: row.username, email: row.email, hashed_password: row.hashed_password, roles: row.roles.unwrap_or_default(), }; // Store result in Redis self.cache .set(&format!("user_by_username:{}", username), &user, 3600) .await .unwrap_or_else(|err| eprintln!("Failed to cache user: {:?}", err)); Ok(user) } pub async fn get_user_by_email(&self, email: &str) -> Result { // Check Redis cache first if let Ok(Some(cached_user)) = self.cache.get::(&format!("user_by_email:{}", email)).await { return Ok(cached_user); } // Fetch from PostgreSQL let row = sqlx::query!( "SELECT id, username, email, hashed_password, roles FROM users WHERE email = $1", email ) .fetch_one(&self.pool) .await?; let user = User { id: row.id, username: row.username, email: row.email, hashed_password: row.hashed_password, roles: row.roles.unwrap_or_default(), }; // Store result in Redis self.cache .set(&format!("user_by_email:{}", email), &user, 3600) .await .unwrap_or_else(|err| eprintln!("Failed to cache user: {:?}", err)); Ok(user) } pub async fn update_user_email(&self, user_id: i32, new_email: &str) -> Result<(), Error> { sqlx::query!( r#" UPDATE users SET email = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2 "#, new_email, user_id ) .execute(&self.pool) .await?; Ok(()) } pub async fn delete_user(&self, user_id: i32) -> Result<(), Error> { sqlx::query!( r#" DELETE FROM users WHERE id = $1 "#, user_id ) .execute(&self.pool) .await?; Ok(()) } }