Add redis caching to getting user notifications and projects [MOD-540] (#723)

* Add redis caching to getting a user's project ids

* Run `cargo sqlx prepare` to update the sqlx-data.json

* Add redis caching for getting user notifications

* Fix new clippy warnings

* Remove log that shouldn't have been committed

* Batch insert of notifications (untested)

* sqlx prepare...

* Fix merge conflict things and use new redis struct

* Fix bug with calling delete_many without any elements (caught by tests)

* cargo sqlx prepare

* Add tests around cache invalidation (and fix bug they caught!)

* Some test reorg based on code review suggestions
This commit is contained in:
Jackson Kruger
2023-10-12 17:52:24 -05:00
committed by GitHub
parent d66270eef0
commit abf4cd71ba
34 changed files with 848 additions and 379 deletions

View File

@@ -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())

View File

@@ -129,8 +129,12 @@ pub async fn notification_read(
if data.user_id == user.id.into() || user.role.is_admin() {
let mut transaction = pool.begin().await?;
database::models::notification_item::Notification::read(id.into(), &mut transaction)
.await?;
database::models::notification_item::Notification::read(
id.into(),
&mut transaction,
&redis,
)
.await?;
transaction.commit().await?;
@@ -172,8 +176,12 @@ pub async fn notification_delete(
if data.user_id == user.id.into() || user.role.is_admin() {
let mut transaction = pool.begin().await?;
database::models::notification_item::Notification::remove(id.into(), &mut transaction)
.await?;
database::models::notification_item::Notification::remove(
id.into(),
&mut transaction,
&redis,
)
.await?;
transaction.commit().await?;
@@ -225,8 +233,12 @@ pub async fn notifications_read(
}
}
database::models::notification_item::Notification::read_many(&notifications, &mut transaction)
.await?;
database::models::notification_item::Notification::read_many(
&notifications,
&mut transaction,
&redis,
)
.await?;
transaction.commit().await?;
@@ -273,6 +285,7 @@ pub async fn notifications_delete(
database::models::notification_item::Notification::remove_many(
&notifications,
&mut transaction,
&redis,
)
.await?;

View File

@@ -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::database::redis::RedisPool;
use crate::file_hosting::{FileHost, FileHostingError};
use crate::models::error::ApiError;
@@ -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) =

View File

@@ -598,7 +598,7 @@ pub async fn project_edit(
new_status: *status,
},
}
.insert_many(notified_members, &mut transaction)
.insert_many(notified_members, &mut transaction, &redis)
.await?;
}

View File

@@ -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::redis::RedisPool;
use crate::database::Project;
use crate::models::notifications::NotificationBody;
@@ -349,6 +349,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?;
@@ -532,7 +533,7 @@ pub async fn add_team_member(
role: new_member.role.clone(),
},
}
.insert(new_member.user_id.into(), &mut transaction)
.insert(new_member.user_id.into(), &mut transaction, &redis)
.await?;
}
TeamAssociationId::Organization(oid) => {
@@ -544,7 +545,7 @@ pub async fn add_team_member(
role: new_member.role.clone(),
},
}
.insert(new_member.user_id.into(), &mut transaction)
.insert(new_member.user_id.into(), &mut transaction, &redis)
.await?;
}
}
@@ -954,6 +955,7 @@ pub async fn remove_team_member(
}
TeamMember::clear_cache(id, &redis).await?;
User::clear_project_cache(&[delete_member.user_id.into()], &redis).await?;
transaction.commit().await?;
Ok(HttpResponse::NoContent().body(""))

View File

@@ -410,6 +410,7 @@ pub async fn thread_send_message(
.insert_many(
members.into_iter().map(|x| x.user_id).collect(),
&mut transaction,
&redis,
)
.await?;
}
@@ -435,7 +436,7 @@ pub async fn thread_send_message(
report_id: Some(report.id.into()),
},
}
.insert(report.reporter, &mut transaction)
.insert(report.reporter, &mut transaction, &redis)
.await?;
}
}

View File

@@ -136,7 +136,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)
@@ -591,11 +591,13 @@ pub async fn user_notifications(
}
let mut notifications: Vec<Notification> =
crate::database::models::notification_item::Notification::get_many_user(id, &**pool)
.await?
.into_iter()
.map(Into::into)
.collect();
crate::database::models::notification_item::Notification::get_many_user(
id, &**pool, &redis,
)
.await?
.into_iter()
.map(Into::into)
.collect();
notifications.sort_by(|a, b| b.created.cmp(&a.created));

View File

@@ -409,7 +409,7 @@ async fn version_create_inner(
version_id,
},
}
.insert_many(users, &mut *transaction)
.insert_many(users, &mut *transaction, redis)
.await?;
let response = Version {