diff --git a/.env b/.env index 16ee17199..01e72f088 100644 --- a/.env +++ b/.env @@ -15,6 +15,7 @@ MEILISEARCH_ADDR=http://localhost:7700 MEILISEARCH_KEY=modrinth REDIS_URL=redis://localhost +REDIS_MAX_CONNECTIONS=10000 BIND_ADDR=127.0.0.1:8000 SELF_ADDR=http://localhost:8000 diff --git a/migrations/20230808043323_threads-index.sql b/migrations/20230808043323_threads-index.sql new file mode 100644 index 000000000..130e5619d --- /dev/null +++ b/migrations/20230808043323_threads-index.sql @@ -0,0 +1,4 @@ +CREATE INDEX threads_report_id + ON threads (report_id); +CREATE INDEX threads_mod_id + ON threads (mod_id); \ No newline at end of file diff --git a/sqlx-data.json b/sqlx-data.json index 33765861a..e8c0fc499 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -1381,51 +1381,6 @@ }, "query": "\n UPDATE users\n SET password = $1\n WHERE (id = $2)\n " }, - "447350097928db863d47d756354cd52668f52f7156dd7f3673a826f7b9aca2fd": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "version_", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "type_", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "created", - "ordinal": 3, - "type_info": "Timestamptz" - }, - { - "name": "major", - "ordinal": 4, - "type_info": "Bool" - } - ], - "nullable": [ - false, - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "Bool", - "Text" - ] - } - }, - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE major = $1 AND type = $2\n ORDER BY created DESC\n " - }, "4514723bdc1eb8a781215075bec51af1cc6fabe88a469338d5a59533eabf80c5": { "describe": { "columns": [ @@ -2962,50 +2917,6 @@ }, "query": "\n DELETE FROM dependencies WHERE mod_dependency_id = $1\n " }, - "78a60cf0febcc6e35b8ffe38f2c021c13ab660c81c4775bbb26004d30242a1a8": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "version_", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "type_", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "created", - "ordinal": 3, - "type_info": "Timestamptz" - }, - { - "name": "major", - "ordinal": 4, - "type_info": "Bool" - } - ], - "nullable": [ - false, - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "Bool" - ] - } - }, - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE major = $1\n ORDER BY created DESC\n " - }, "7916fe4f04067324ae05598ec9dc6f97f18baf9eda30c64f32677158ada87478": { "describe": { "columns": [], @@ -5616,50 +5527,6 @@ }, "query": "SELECT EXISTS(SELECT 1 FROM team_members WHERE id=$1)" }, - "e8ad94314ec2972c3102041b1bf06872c8e4c8a55156a17334a0e317fe41b784": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "version_", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "type_", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "created", - "ordinal": 3, - "type_info": "Timestamptz" - }, - { - "name": "major", - "ordinal": 4, - "type_info": "Bool" - } - ], - "nullable": [ - false, - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE type = $1\n ORDER BY created DESC\n " - }, "e8d4589132b094df1e7a3ca0440344fc8013c0d20b3c71a1142ccbee91fb3c70": { "describe": { "columns": [ diff --git a/src/database/models/categories.rs b/src/database/models/categories.rs index fd7dce6d3..4a99a750e 100644 --- a/src/database/models/categories.rs +++ b/src/database/models/categories.rs @@ -3,7 +3,11 @@ use super::DatabaseError; use chrono::DateTime; use chrono::Utc; use futures::TryStreamExt; -use serde::Deserialize; +use redis::cmd; +use serde::{Deserialize, Serialize}; + +const TAGS_NAMESPACE: &str = "tags"; +const DEFAULT_EXPIRY: i64 = 1800; // 30 minutes pub struct ProjectType { pub id: ProjectTypeId, @@ -15,6 +19,7 @@ pub struct SideType { pub name: String, } +#[derive(Serialize, Deserialize)] pub struct Loader { pub id: LoaderId, pub loader: String, @@ -22,7 +27,7 @@ pub struct Loader { pub supported_project_types: Vec, } -#[derive(Clone, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug)] pub struct GameVersion { pub id: GameVersionId, pub version: String, @@ -32,6 +37,7 @@ pub struct GameVersion { pub major: bool, } +#[derive(Serialize, Deserialize)] pub struct Category { pub id: CategoryId, pub category: String, @@ -45,6 +51,7 @@ pub struct ReportType { pub report_type: String, } +#[derive(Serialize, Deserialize)] pub struct DonationPlatform { pub id: DonationPlatformId, pub short: String, @@ -91,10 +98,24 @@ impl Category { Ok(result.map(|r| CategoryId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:category", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT c.id id, c.category category, c.icon icon, c.header category_header, pt.name project_type @@ -116,6 +137,14 @@ impl Category { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:category", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } @@ -138,10 +167,24 @@ impl Loader { Ok(result.map(|r| LoaderId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:loader", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT l.id id, l.loader loader, l.icon icon, @@ -169,6 +212,14 @@ impl Loader { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:loader", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } @@ -205,10 +256,24 @@ impl GameVersion { Ok(result.map(|r| GameVersionId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:game_version", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major FROM game_versions gv @@ -226,6 +291,14 @@ impl GameVersion { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:game_version", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } @@ -233,75 +306,27 @@ impl GameVersion { version_type_option: Option<&str>, major_option: Option, exec: E, + redis: &deadpool_redis::Pool, ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - let result; + let result = Self::list(exec, redis) + .await? + .into_iter() + .filter(|x| { + let mut bool = true; - if let Some(version_type) = version_type_option { - if let Some(major) = major_option { - result = sqlx::query!( - " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv - WHERE major = $1 AND type = $2 - ORDER BY created DESC - ", - major, - version_type - ) - .fetch_many(exec) - .try_filter_map(|e| async { Ok(e.right().map(|c| GameVersion { - id: GameVersionId(c.id), - version: c.version_, - type_: c.type_, - created: c.created, - major: c.major, - })) }) - .try_collect::>() - .await?; - } else { - result = sqlx::query!( - " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv - WHERE type = $1 - ORDER BY created DESC - ", - version_type - ) - .fetch_many(exec) - .try_filter_map(|e| async { Ok(e.right().map(|c| GameVersion { - id: GameVersionId(c.id), - version: c.version_, - type_: c.type_, - created: c.created, - major: c.major, - })) }) - .try_collect::>() - .await?; - } - } else if let Some(major) = major_option { - result = sqlx::query!( - " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv - WHERE major = $1 - ORDER BY created DESC - ", - major - ) - .fetch_many(exec) - .try_filter_map(|e| async { Ok(e.right().map(|c| GameVersion { - id: GameVersionId(c.id), - version: c.version_, - type_: c.type_, - created: c.created, - major: c.major, - })) }) - .try_collect::>() - .await?; - } else { - result = Vec::new(); - } + if let Some(version_type) = version_type_option { + bool &= &*x.type_ == version_type; + } + if let Some(major) = major_option { + bool &= x.major == major; + } + + bool + }) + .collect(); Ok(result) } @@ -381,10 +406,24 @@ impl DonationPlatform { Ok(result.map(|r| DonationPlatformId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:donation_platform", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT id, short, name FROM donation_platforms @@ -401,6 +440,14 @@ impl DonationPlatform { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:donation_platform", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } @@ -423,10 +470,24 @@ impl ReportType { Ok(result.map(|r| ReportTypeId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:report_type", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT name FROM report_types @@ -437,6 +498,14 @@ impl ReportType { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:report_type", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } @@ -459,10 +528,24 @@ impl ProjectType { Ok(result.map(|r| ProjectTypeId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:project_type", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT name FROM project_types @@ -473,6 +556,14 @@ impl ProjectType { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:project_type", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } @@ -495,10 +586,24 @@ impl SideType { Ok(result.map(|r| SideTypeId(r.id))) } - pub async fn list<'a, E>(exec: E) -> Result, DatabaseError> + pub async fn list<'a, E>( + exec: E, + redis: &deadpool_redis::Pool, + ) -> Result, DatabaseError> where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { + let mut redis = redis.get().await?; + let res = cmd("GET") + .arg(format!("{}:side_type", TAGS_NAMESPACE)) + .query_async::<_, Option>(&mut redis) + .await? + .and_then(|x| serde_json::from_str::>(&x).ok()); + + if let Some(res) = res { + return Ok(res); + } + let result = sqlx::query!( " SELECT name FROM side_types @@ -509,6 +614,14 @@ impl SideType { .try_collect::>() .await?; + cmd("SET") + .arg(format!("{}:side_type", TAGS_NAMESPACE)) + .arg(serde_json::to_string(&result)?) + .arg("EX") + .arg(DEFAULT_EXPIRY) + .query_async::<_, ()>(&mut redis) + .await?; + Ok(result) } } diff --git a/src/database/models/ids.rs b/src/database/models/ids.rs index fbfa10358..055e75744 100644 --- a/src/database/models/ids.rs +++ b/src/database/models/ids.rs @@ -161,13 +161,13 @@ pub struct DonationPlatformId(pub i32); #[derive(Copy, Clone, Debug, Type, PartialEq, Eq, Hash, Serialize, Deserialize)] #[sqlx(transparent)] pub struct VersionId(pub i64); -#[derive(Copy, Clone, Debug, Type, Deserialize)] +#[derive(Copy, Clone, Debug, Type, Deserialize, Serialize)] #[sqlx(transparent)] pub struct GameVersionId(pub i32); -#[derive(Copy, Clone, Debug, Type)] +#[derive(Copy, Clone, Debug, Type, Serialize, Deserialize)] #[sqlx(transparent)] pub struct LoaderId(pub i32); -#[derive(Copy, Clone, Debug, Type)] +#[derive(Copy, Clone, Debug, Type, Serialize, Deserialize)] #[sqlx(transparent)] pub struct CategoryId(pub i32); diff --git a/src/database/models/project_item.rs b/src/database/models/project_item.rs index d03eef0ec..3dbb9c4bb 100644 --- a/src/database/models/project_item.rs +++ b/src/database/models/project_item.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; const PROJECTS_NAMESPACE: &str = "projects"; const PROJECTS_SLUGS_NAMESPACE: &str = "projects_slugs"; const PROJECTS_DEPENDENCIES_NAMESPACE: &str = "projects_dependencies"; -const DEFAULT_EXPIRY: i64 = 3600; // 60 minutes +const DEFAULT_EXPIRY: i64 = 1800; // 30 minutes #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DonationUrl { @@ -524,7 +524,8 @@ impl Project { { remaining_strings.retain(|x| { &to_base62(project.inner.id.0 as u64) != x - && project.inner.slug.as_ref() != Some(x) + && project.inner.slug.as_ref().map(|x| x.to_lowercase()) + != Some(x.to_lowercase()) }); found_projects.push(project); continue; diff --git a/src/database/models/user_item.rs b/src/database/models/user_item.rs index 6eeea1d08..f93a137f6 100644 --- a/src/database/models/user_item.rs +++ b/src/database/models/user_item.rs @@ -185,8 +185,10 @@ impl User { for user in users { if let Some(user) = user.and_then(|x| serde_json::from_str::(&x).ok()) { - remaining_strings - .retain(|x| &to_base62(user.id.0 as u64) != x && &user.username != x); + remaining_strings.retain(|x| { + &to_base62(user.id.0 as u64) != x + && user.username.to_lowercase() != x.to_lowercase() + }); found_users.push(user); continue; } diff --git a/src/database/models/version_item.rs b/src/database/models/version_item.rs index fa223fbdb..a763f5740 100644 --- a/src/database/models/version_item.rs +++ b/src/database/models/version_item.rs @@ -716,7 +716,7 @@ impl Version { for (key, mut files) in save_files { cmd("SET") - .arg(format!("{}:{}", VERSIONS_NAMESPACE, key)) + .arg(format!("{}:{}", VERSION_FILES_NAMESPACE, key)) .arg(serde_json::to_string(&files)?) .arg("EX") .arg(DEFAULT_EXPIRY) diff --git a/src/main.rs b/src/main.rs index 4897777f3..eb49a5d64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,9 +79,17 @@ async fn main() -> std::io::Result<()> { .expect("Database connection failed"); // Redis connector - let redis_cfg = Config::from_url(dotenvy::var("REDIS_URL").expect("Redis URL not set")); - let redis_pool = redis_cfg - .create_pool(Some(Runtime::Tokio1)) + let redis_pool = Config::from_url(dotenvy::var("REDIS_URL").expect("Redis URL not set")) + .builder() + .expect("Error building Redis pool") + .max_size( + dotenvy::var("DATABASE_MAX_CONNECTIONS") + .ok() + .and_then(|x| x.parse().ok()) + .unwrap_or(10000), + ) + .runtime(Runtime::Tokio1) + .build() .expect("Redis connection failed"); let storage_backend = dotenvy::var("STORAGE_BACKEND").unwrap_or_else(|_| "local".to_string()); @@ -175,6 +183,7 @@ async fn main() -> std::io::Result<()> { // Reminding moderators to review projects which have been in the queue longer than 40hr let pool_ref = pool.clone(); + let redis_ref = redis_pool.clone(); let webhook_message_sent = Arc::new(Mutex::new(Vec::<( database::models::ProjectId, DateTime, @@ -182,6 +191,7 @@ async fn main() -> std::io::Result<()> { scheduler.run(std::time::Duration::from_secs(10 * 60), move || { let pool_ref = pool_ref.clone(); + let redis_ref = redis_ref.clone(); let webhook_message_sent_ref = webhook_message_sent.clone(); info!("Checking reviewed projects submitted more than 40hrs ago"); @@ -217,6 +227,7 @@ async fn main() -> std::io::Result<()> { util::webhook::send_discord_webhook( project.into(), &pool_ref, + &redis_ref, webhook_url, Some("<@&783155186491195394> This project has been in the queue for over 40 hours!".to_string()), ) diff --git a/src/routes/v2/project_creation.rs b/src/routes/v2/project_creation.rs index 39430efb6..4a1ffaa2f 100644 --- a/src/routes/v2/project_creation.rs +++ b/src/routes/v2/project_creation.rs @@ -367,8 +367,8 @@ async fn project_create_inner( let mut versions_map = std::collections::HashMap::new(); let mut gallery_urls = Vec::new(); - let all_game_versions = models::categories::GameVersion::list(&mut *transaction).await?; - let all_loaders = models::categories::Loader::list(&mut *transaction).await?; + let all_game_versions = models::categories::GameVersion::list(&mut *transaction, redis).await?; + let all_loaders = models::categories::Loader::list(&mut *transaction, redis).await?; { // The first multipart field must be named "data" and contain a @@ -836,9 +836,15 @@ async fn project_create_inner( if status == ProjectStatus::Processing { if let Ok(webhook_url) = dotenvy::var("MODERATION_DISCORD_WEBHOOK") { - crate::util::webhook::send_discord_webhook(response.id, pool, webhook_url, None) - .await - .ok(); + crate::util::webhook::send_discord_webhook( + response.id, + pool, + redis, + webhook_url, + None, + ) + .await + .ok(); } } diff --git a/src/routes/v2/projects.rs b/src/routes/v2/projects.rs index dd611317f..d7c82b359 100644 --- a/src/routes/v2/projects.rs +++ b/src/routes/v2/projects.rs @@ -504,6 +504,7 @@ pub async fn project_edit( crate::util::webhook::send_discord_webhook( project_item.inner.id.into(), &pool, + &redis, webhook_url, None, ) @@ -530,6 +531,7 @@ pub async fn project_edit( crate::util::webhook::send_discord_webhook( project_item.inner.id.into(), &pool, + &redis, webhook_url, None, ) @@ -1251,8 +1253,9 @@ pub async fn projects_edit( let team_members = database::models::TeamMember::get_from_team_full_many(&team_ids, &**pool, &redis).await?; - let categories = database::models::categories::Category::list(&**pool).await?; - let donation_platforms = database::models::categories::DonationPlatform::list(&**pool).await?; + let categories = database::models::categories::Category::list(&**pool, &redis).await?; + let donation_platforms = + database::models::categories::DonationPlatform::list(&**pool, &redis).await?; let mut transaction = pool.begin().await?; diff --git a/src/routes/v2/tags.rs b/src/routes/v2/tags.rs index 2a38954be..9307ae3e3 100644 --- a/src/routes/v2/tags.rs +++ b/src/routes/v2/tags.rs @@ -30,8 +30,11 @@ pub struct CategoryData { } #[get("category")] -pub async fn category_list(pool: web::Data) -> Result { - let results = Category::list(&**pool) +pub async fn category_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let results = Category::list(&**pool, &redis) .await? .into_iter() .map(|x| CategoryData { @@ -53,8 +56,11 @@ pub struct LoaderData { } #[get("loader")] -pub async fn loader_list(pool: web::Data) -> Result { - let mut results = Loader::list(&**pool) +pub async fn loader_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let mut results = Loader::list(&**pool, &redis) .await? .into_iter() .map(|x| LoaderData { @@ -88,11 +94,12 @@ pub struct GameVersionQuery { pub async fn game_version_list( pool: web::Data, query: web::Query, + redis: web::Data, ) -> Result { let results: Vec = if query.type_.is_some() || query.major.is_some() { - GameVersion::list_filter(query.type_.as_deref(), query.major, &**pool).await? + GameVersion::list_filter(query.type_.as_deref(), query.major, &**pool, &redis).await? } else { - GameVersion::list(&**pool).await? + GameVersion::list(&**pool, &redis).await? } .into_iter() .map(|x| GameVersionQueryData { @@ -163,8 +170,11 @@ pub struct DonationPlatformQueryData { } #[get("donation_platform")] -pub async fn donation_platform_list(pool: web::Data) -> Result { - let results: Vec = DonationPlatform::list(&**pool) +pub async fn donation_platform_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let results: Vec = DonationPlatform::list(&**pool, &redis) .await? .into_iter() .map(|x| DonationPlatformQueryData { @@ -176,19 +186,28 @@ pub async fn donation_platform_list(pool: web::Data) -> Result) -> Result { - let results = ReportType::list(&**pool).await?; +pub async fn report_type_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let results = ReportType::list(&**pool, &redis).await?; Ok(HttpResponse::Ok().json(results)) } #[get("project_type")] -pub async fn project_type_list(pool: web::Data) -> Result { - let results = ProjectType::list(&**pool).await?; +pub async fn project_type_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let results = ProjectType::list(&**pool, &redis).await?; Ok(HttpResponse::Ok().json(results)) } #[get("side_type")] -pub async fn side_type_list(pool: web::Data) -> Result { - let results = SideType::list(&**pool).await?; +pub async fn side_type_list( + pool: web::Data, + redis: web::Data, +) -> Result { + let results = SideType::list(&**pool, &redis).await?; Ok(HttpResponse::Ok().json(results)) } diff --git a/src/routes/v2/version_creation.rs b/src/routes/v2/version_creation.rs index caf972dca..1ea045d10 100644 --- a/src/routes/v2/version_creation.rs +++ b/src/routes/v2/version_creation.rs @@ -135,8 +135,8 @@ async fn version_create_inner( let mut initial_version_data = None; let mut version_builder = None; - let all_game_versions = models::categories::GameVersion::list(&mut *transaction).await?; - let all_loaders = models::categories::Loader::list(&mut *transaction).await?; + let all_game_versions = models::categories::GameVersion::list(&mut *transaction, redis).await?; + let all_loaders = models::categories::Loader::list(&mut *transaction, redis).await?; let user = get_user_from_headers( &req, @@ -561,7 +561,8 @@ async fn upload_file_to_version_inner( .await? .name; - let all_game_versions = models::categories::GameVersion::list(&mut *transaction).await?; + let all_game_versions = + models::categories::GameVersion::list(&mut *transaction, &redis).await?; let mut error = None; while let Some(item) = payload.next().await { diff --git a/src/routes/v2/versions.rs b/src/routes/v2/versions.rs index a3080c1da..fca214dee 100644 --- a/src/routes/v2/versions.rs +++ b/src/routes/v2/versions.rs @@ -115,8 +115,13 @@ pub async fn version_list( // Attempt to populate versions with "auto featured" versions if response.is_empty() && !versions.is_empty() && filters.featured.unwrap_or(false) { let (loaders, game_versions) = futures::future::try_join( - database::models::categories::Loader::list(&**pool), - database::models::categories::GameVersion::list_filter(None, Some(true), &**pool), + database::models::categories::Loader::list(&**pool, &redis), + database::models::categories::GameVersion::list_filter( + None, + Some(true), + &**pool, + &redis, + ), ) .await?; diff --git a/src/util/webhook.rs b/src/util/webhook.rs index 89b8d3d63..86dae92cd 100644 --- a/src/util/webhook.rs +++ b/src/util/webhook.rs @@ -72,10 +72,11 @@ const PLUGIN_LOADERS: &[&str] = &[ pub async fn send_discord_webhook( project_id: ProjectId, pool: &PgPool, + redis: &deadpool_redis::Pool, webhook_url: String, message: Option, ) -> Result<(), ApiError> { - let all_game_versions = GameVersion::list(pool).await?; + let all_game_versions = GameVersion::list(pool, redis).await?; let row = sqlx::query!(