Ref-count Redis pool internals, fix project creation slug/ID collision (#5302)

* Ref-count Redis pool internals, fix project creation slug/ID collision

* cargo sqlx prepare
This commit is contained in:
aecsocket
2026-02-05 05:18:33 +00:00
committed by GitHub
parent 9105a68923
commit b1954be2c7
5 changed files with 16 additions and 32 deletions

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT EXISTS(SELECT 1 FROM mods WHERE slug = LOWER($1))\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "f8be3053274b00ee9743e798886696062009c5f681baaf29dfc24cfbbda93742"
}

View File

@@ -14,6 +14,7 @@ use std::collections::HashMap;
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use std::future::Future; use std::future::Future;
use std::hash::Hash; use std::hash::Hash;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tracing::{Instrument, info, info_span}; use tracing::{Instrument, info, info_span};
use util::{cmd, redis_pipe}; use util::{cmd, redis_pipe};
@@ -27,20 +28,20 @@ const ACTUAL_EXPIRY: i64 = 60 * 30; // 30 minutes
pub struct RedisPool { pub struct RedisPool {
pub url: String, pub url: String,
pub pool: deadpool_redis::Pool, pub pool: deadpool_redis::Pool,
cache_list: DashMap<String, util::CacheSubscriber>, cache_list: Arc<DashMap<String, util::CacheSubscriber>>,
meta_namespace: String, meta_namespace: Arc<str>,
} }
pub struct RedisConnection { pub struct RedisConnection {
pub connection: deadpool_redis::Connection, pub connection: deadpool_redis::Connection,
meta_namespace: String, meta_namespace: Arc<str>,
} }
impl RedisPool { impl RedisPool {
// initiate a new redis pool // initiate a new redis pool
// testing pool uses a hashmap to mimic redis behaviour for very small data sizes (ie: tests) // testing pool uses a hashmap to mimic redis behaviour for very small data sizes (ie: tests)
// PANICS: production pool will panic if redis url is not set // PANICS: production pool will panic if redis url is not set
pub fn new(meta_namespace: Option<String>) -> Self { pub fn new(meta_namespace: impl Into<Arc<str>>) -> Self {
let wait_timeout = let wait_timeout =
dotenvy::var("REDIS_WAIT_TIMEOUT_MS").ok().map_or_else( dotenvy::var("REDIS_WAIT_TIMEOUT_MS").ok().map_or_else(
|| Duration::from_millis(15000), || Duration::from_millis(15000),
@@ -71,8 +72,8 @@ impl RedisPool {
let pool = RedisPool { let pool = RedisPool {
url, url,
pool, pool,
cache_list: DashMap::with_capacity(2048), cache_list: Arc::new(DashMap::with_capacity(2048)),
meta_namespace: meta_namespace.unwrap_or("".to_string()), meta_namespace: meta_namespace.into(),
}; };
let redis_min_connections = dotenvy::var("REDIS_MIN_CONNECTIONS") let redis_min_connections = dotenvy::var("REDIS_MIN_CONNECTIONS")

View File

@@ -117,7 +117,7 @@ async fn app() -> std::io::Result<()> {
.expect("Database connection failed"); .expect("Database connection failed");
// Redis connector // Redis connector
let redis_pool = RedisPool::new(None); let redis_pool = RedisPool::new("");
let storage_backend = let storage_backend =
dotenvy::var("STORAGE_BACKEND").unwrap_or_else(|_| "local".to_string()); dotenvy::var("STORAGE_BACKEND").unwrap_or_else(|_| "local".to_string());

View File

@@ -497,7 +497,12 @@ async fn project_create_inner(
{ {
let results = sqlx::query!( let results = sqlx::query!(
" "
SELECT EXISTS(SELECT 1 FROM mods WHERE slug = LOWER($1)) SELECT EXISTS(
SELECT 1 FROM mods
WHERE
slug = LOWER($1)
OR text_id_lower = LOWER($1)
)
", ",
create_data.slug create_data.slug
) )

View File

@@ -89,7 +89,7 @@ impl TemporaryDatabase {
println!("Migrations complete"); println!("Migrations complete");
// Gets new Redis pool // Gets new Redis pool
let redis_pool = RedisPool::new(Some(temp_database_name.clone())); let redis_pool = RedisPool::new(temp_database_name.clone());
// Create new meilisearch config // Create new meilisearch config
let search_config = let search_config =
@@ -194,7 +194,7 @@ impl TemporaryDatabase {
pool: pool.clone(), pool: pool.clone(),
ro_pool: ReadOnlyPgPool::from(pool.clone()), ro_pool: ReadOnlyPgPool::from(pool.clone()),
database_name: TEMPLATE_DATABASE_NAME.to_string(), database_name: TEMPLATE_DATABASE_NAME.to_string(),
redis_pool: RedisPool::new(Some(name.clone())), redis_pool: RedisPool::new(name.clone()),
search_config: search::SearchConfig::new(Some(name)), search_config: search::SearchConfig::new(Some(name)),
}; };
let setup_api = let setup_api =