Closed JimFuller-RedHat closed 2 months ago
For sure. They are very complex queries, and definitely are succumbing to a 1+N queries that we could probably optimize a bit.
it looks like we are looping through some queries, for example with api/v1/product
pub async fn from_entities(
products: &[product::Model],
tx: &ConnectionOrTransaction<'_>,
) -> Result<Vec<Self>, Error> {
let mut summaries = Vec::new();
for product in products {
summaries.push(ProductSummary::from_entity(product, tx).await?);
}
Ok(summaries)
}
even if from_entity takes advantage of find_related, the top level ensures multiple calls and pushes.
same with api/v1/vulnerability
impl VulnerabilitySummary {
pub async fn from_entities(
vulnerabilities: &[vulnerability::Model],
tx: &ConnectionOrTransaction<'_>,
) -> Result<Vec<Self>, Error> {
let advisories = vulnerabilities
.load_many_to_many(advisory::Entity::find(), advisory_vulnerability::Entity, tx)
.await?;
let mut summaries = Vec::new();
for (vuln, advisories) in vulnerabilities.iter().zip(advisories.iter()) {
let cvss3 = cvss3::Entity::find()
.filter(cvss3::Column::VulnerabilityId.eq(&vuln.id))
.all(tx)
.await?;
let total_score = cvss3
.iter()
.map(|e| {
let base = Cvss3Base::from(e.clone());
base.score().value()
})
.reduce(|accum, e| accum + e);
let average_score = total_score.map(|total| Score::new(total / cvss3.len() as f64));
summaries.push(VulnerabilitySummary {
head: VulnerabilityHead::from_vulnerability_entity(vuln, tx).await?,
average_severity: average_score.map(|score| score.severity().to_string()),
average_score: average_score.map(|score| score.value()),
advisories: VulnerabilityAdvisoryHead::from_entities(vuln, advisories, tx).await?,
});
}
Ok(summaries)
}
same with api/v1/vulnerability
This is currently on my plate relating to #411
the past few weeks of work have addressed - will open a new issue based on more testing if required
loadtest revealed
we should perform code/data analysis why api/v1/product and api/v1/vulnerability degrade