Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Add redis caching to getting a user's project ids
Browse files Browse the repository at this point in the history
  • Loading branch information
OmegaJak committed Oct 2, 2023
1 parent a1b59d4 commit 0967893
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 11 deletions.
12 changes: 9 additions & 3 deletions src/database/models/project_item.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::ids::*;
use super::{ids::*, User};
use crate::database::models;
use crate::database::models::DatabaseError;
use crate::models::ids::base62_impl::{parse_base62, to_base62};
use crate::models::projects::{MonetizationStatus, ProjectStatus};
use chrono::{DateTime, Utc};
use futures::TryStreamExt;
use redis::cmd;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -404,16 +405,21 @@ impl Project {

models::TeamMember::clear_cache(project.inner.team_id, redis).await?;

sqlx::query!(
let affected_user_ids = sqlx::query!(
"
DELETE FROM team_members
WHERE team_id = $1
RETURNING user_id
",
project.inner.team_id as TeamId,
)
.execute(&mut *transaction)
.fetch_many(&mut *transaction)
.try_filter_map(|e| async { Ok(e.right().map(|x| UserId(x.user_id))) })
.try_collect::<Vec<_>>()
.await?;

User::clear_project_cache(&affected_user_ids, redis).await?;

sqlx::query!(
"
DELETE FROM teams
Expand Down
46 changes: 42 additions & 4 deletions src/database/models/user_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};

const USERS_NAMESPACE: &str = "users";
const USER_USERNAMES_NAMESPACE: &str = "users_usernames";
// const USERS_PROJECTS_NAMESPACE: &str = "users_projects";
const USERS_PROJECTS_NAMESPACE: &str = "users_projects";
const DEFAULT_EXPIRY: i64 = 1800; // 30 minutes

#[derive(Deserialize, Serialize, Clone, Debug)]
Expand Down Expand Up @@ -298,13 +298,27 @@ impl User {
pub async fn get_projects<'a, E>(
user_id: UserId,
exec: E,
) -> Result<Vec<ProjectId>, sqlx::Error>
redis: &deadpool_redis::Pool,
) -> Result<Vec<ProjectId>, DatabaseError>
where
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
{
use futures::stream::TryStreamExt;

let projects = sqlx::query!(
let mut redis = redis.get().await?;

let cached_projects = cmd("GET")
.arg(format!("{}:{}", USERS_PROJECTS_NAMESPACE, user_id.0))
.query_async::<_, Option<String>>(&mut redis)
.await?
.and_then(|x| serde_json::from_str::<Vec<ProjectId>>(&x).ok());

if let Some(projects) = cached_projects {
log::info!("Returning cached!");
return Ok(projects);
}

let db_projects = sqlx::query!(
"
SELECT m.id FROM mods m
INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.accepted = TRUE
Expand All @@ -318,7 +332,15 @@ impl User {
.try_collect::<Vec<ProjectId>>()
.await?;

Ok(projects)
cmd("SET")
.arg(format!("{}:{}", USERS_PROJECTS_NAMESPACE, user_id.0))
.arg(serde_json::to_string(&db_projects)?)
.arg("EX")
.arg(DEFAULT_EXPIRY)
.query_async::<_, ()>(&mut redis)
.await?;

Ok(db_projects)
}

pub async fn get_collections<'a, E>(
Expand Down Expand Up @@ -392,6 +414,22 @@ impl User {
Ok(())
}

pub async fn clear_project_cache(
user_ids: &[UserId],
redis: &deadpool_redis::Pool,
) -> Result<(), DatabaseError> {
let mut redis = redis.get().await?;
let mut cmd = cmd("DEL");

for user_id in user_ids {
cmd.arg(format!("{}:{}", USERS_PROJECTS_NAMESPACE, user_id.0));
}

cmd.query_async(&mut redis).await?;

Ok(())
}

pub async fn remove(
id: UserId,
full: bool,
Expand Down
2 changes: 1 addition & 1 deletion src/routes/v2/analytics_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ async fn filter_allowed_ids(
if project_ids.is_none() && version_ids.is_none() {
if let Some(user) = &user_option {
project_ids = Some(
user_item::User::get_projects(user.id.into(), &***pool)
user_item::User::get_projects(user.id.into(), &***pool, &redis)
.await?
.into_iter()
.map(|x| ProjectId::from(x).to_string())
Expand Down
3 changes: 2 additions & 1 deletion src/routes/v2/project_creation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::version_creation::InitialVersionData;
use crate::auth::{get_user_from_headers, AuthenticationError};
use crate::database::models::thread_item::ThreadBuilder;
use crate::database::models::{self, image_item};
use crate::database::models::{self, image_item, User};
use crate::file_hosting::{FileHost, FileHostingError};
use crate::models::error::ApiError;
use crate::models::ids::ImageId;
Expand Down Expand Up @@ -791,6 +791,7 @@ async fn project_create_inner(
let now = Utc::now();

let id = project_builder_actual.insert(&mut *transaction).await?;
User::clear_project_cache(&[current_user.id.into()], redis).await?;

for image_id in project_create_data.uploaded_images {
if let Some(db_image) =
Expand Down
4 changes: 3 additions & 1 deletion src/routes/v2/teams.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::auth::{get_user_from_headers, is_authorized};
use crate::database::models::notification_item::NotificationBuilder;
use crate::database::models::team_item::TeamAssociationId;
use crate::database::models::{Organization, Team, TeamMember};
use crate::database::models::{Organization, Team, TeamMember, User};
use crate::database::Project;
use crate::models::notifications::NotificationBody;
use crate::models::pats::Scopes;
Expand Down Expand Up @@ -348,6 +348,7 @@ pub async fn join_team(
)
.await?;

User::clear_project_cache(&[current_user.id.into()], &redis).await?;
TeamMember::clear_cache(team_id, &redis).await?;

transaction.commit().await?;
Expand Down Expand Up @@ -954,6 +955,7 @@ pub async fn remove_team_member(
}

TeamMember::clear_cache(id, &redis).await?;
User::clear_project_cache(&[current_user.id.into()], &redis).await?;

transaction.commit().await?;
Ok(HttpResponse::NoContent().body(""))
Expand Down
2 changes: 1 addition & 1 deletion src/routes/v2/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ pub async fn projects_list(
.map(|y| y.role.is_mod() || y.id == user_id)
.unwrap_or(false);

let project_data = User::get_projects(id, &**pool).await?;
let project_data = User::get_projects(id, &**pool, &redis).await?;

let response: Vec<_> =
crate::database::Project::get_many_ids(&project_data, &**pool, &redis)
Expand Down

0 comments on commit 0967893

Please sign in to comment.