perf: Attribution route perf improvements (#6489)

* Attribution route perf improvements

* fix clippy

* clear exemptions when user attempts to scan their file

* Increase Redis TTL/refresh time
This commit is contained in:
aecsocket
2026-06-24 17:48:35 +02:00
committed by GitHub
parent 29110890e1
commit c392c85917
19 changed files with 333 additions and 127 deletions
@@ -808,6 +808,18 @@ impl DBVersion {
}
).await?;
let dependency_attributions =
crate::queue::file_scan::get_dependency_attributions(
&mut exec,
&version_ids
.iter()
.copied()
.map(DBVersionId)
.collect_vec(),
)
.await
.unwrap_or_default();
let res = sqlx::query!(
r#"
SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number,
@@ -832,6 +844,19 @@ impl DBVersion {
let hashes = hashes.remove(&version_id).map(|x|x.1).unwrap_or_default();
let version_fields = version_fields.remove(&version_id).map(|x|x.1).unwrap_or_default();
let dependencies = dependencies.remove(&version_id).map(|x|x.1).unwrap_or_default();
let dependencies = dependencies
.into_iter()
.map(|mut dependency| {
if let Some(attr) = dependency_attributions.get(&dependency.id)
&& (attr.attribution.flame_project.is_some()
|| attr.attribution.resolution.is_some())
{
dependency.attribution = Some(attr.attribution.clone());
}
dependency
})
.collect_vec();
let loader_fields = loader_fields.iter()
.filter(|x| loader_loader_field_ids.contains(&x.id))
@@ -1030,6 +1055,22 @@ impl DBVersion {
.await?;
Ok(())
}
pub async fn clear_cache_ids(
version_ids: &[DBVersionId],
redis: &RedisPool,
) -> Result<(), DatabaseError> {
let mut redis = redis.connect().await?;
redis
.delete_many(
version_ids
.iter()
.map(|id| (VERSIONS_NAMESPACE, Some(id.0.to_string()))),
)
.await?;
Ok(())
}
}
#[derive(Clone, Deserialize, Serialize)]
+15 -3
View File
@@ -25,6 +25,8 @@ pub mod util;
const DEFAULT_EXPIRY: i64 = 60 * 60 * 12; // 12 hours
const ACTUAL_EXPIRY: i64 = 60 * 30; // 30 minutes
const VERSION_DEFAULT_EXPIRY: i64 = 60 * 60 * 48; // 48 hours
const VERSION_ACTUAL_EXPIRY: i64 = 60 * 60 * 24; // 24 hours
// Bound how many commands we send in a single Redis pipeline. The multiplexed
// connection's BytesMut write buffer keeps its peak capacity for the life of
@@ -39,6 +41,15 @@ const MGET_CHUNK_SIZE: usize = 32;
// BytesMut peak capacity that builds up under steady load.
const REDIS_MAX_CONN_AGE: Duration = Duration::from_secs(120);
fn cache_expiries(namespace: &str) -> (i64, i64) {
match namespace {
"versions" | "versions_files" => {
(VERSION_DEFAULT_EXPIRY, VERSION_ACTUAL_EXPIRY)
}
_ => (DEFAULT_EXPIRY, ACTUAL_EXPIRY),
}
}
#[derive(Clone)]
pub struct RedisPool {
pub url: String,
@@ -372,6 +383,7 @@ impl RedisPool {
.instrument(info_span!("get cached values"))
};
let (default_expiry, actual_expiry) = cache_expiries(namespace);
let current_time = Utc::now();
let mut expired_values = HashMap::new();
@@ -379,7 +391,7 @@ impl RedisPool {
let mut cached_values = cached_values_raw
.into_iter()
.filter_map(|(key, val)| {
if Utc.timestamp_opt(val.iat + ACTUAL_EXPIRY, 0).unwrap()
if Utc.timestamp_opt(val.iat + actual_expiry, 0).unwrap()
< current_time
{
expired_values.insert(val.key.to_string(), val);
@@ -481,7 +493,7 @@ impl RedisPool {
self.meta_namespace
),
serde_json::to_string(&value)?,
DEFAULT_EXPIRY as u64,
default_expiry as u64,
);
pipe_cmds += 1;
@@ -501,7 +513,7 @@ impl RedisPool {
self.meta_namespace, actual_slug
),
key.to_string(),
DEFAULT_EXPIRY as u64,
default_expiry as u64,
);
pipe_cmds += 1;
}