Skip to content

Commit 93bb2fe

Browse files
authored
fix: slowness in download endpoint (#1065)
1. It was meant to limit to most recent 5 versions, but it was querying all. 2. It was doing a bunch of queries in series instead of querying all versions in a single call.
1 parent 1e8a1b0 commit 93bb2fe

File tree

7 files changed

+92
-55
lines changed

7 files changed

+92
-55
lines changed

api/.sqlx/query-d85e9c34ba1e0bf729603f81093c42c4f48fa8ab9ea6330062c4b5fbc7df09e7.json renamed to api/.sqlx/query-47775e53578b988ebd14f2d9bbbeb81c82a13ab9a73ac6f6d158fde2cd563188.json

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/.sqlx/query-7b88c2e5072155bf7adaad3cfad86da140bf9bea4825836a563af75da02815b3.json renamed to api/.sqlx/query-c4621e8ce78b0df7bc634ff805ebbe65af37e70a1af5e25e6cc6e2f1354cea61.json

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/src/api/package.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,35 +1647,51 @@ pub async fn get_downloads_handler(
16471647
let current = Utc::now();
16481648
let start = current - chrono::Duration::days(90);
16491649

1650-
let total = db
1651-
.get_package_downloads_24h(&scope, &package, start, current)
1652-
.await?;
1650+
let total_fut = async {
1651+
db.get_package_downloads_24h(&scope, &package, start, current)
1652+
.await
1653+
.map_err(ApiError::from)
1654+
};
16531655

1654-
let recent_versions = db
1655-
.list_latest_unyanked_versions_for_package(&scope, &package, 5)
1656-
.await?;
1656+
let recent_versions_fut = async {
1657+
let recent_versions = db
1658+
.list_latest_unyanked_versions_for_package(&scope, &package, 5)
1659+
.await?;
16571660

1658-
let versions = futures::stream::iter(recent_versions.into_iter())
1659-
.then(|version| async {
1660-
let res = db
1661-
.get_package_version_downloads_24h(
1662-
&scope, &package, &version, start, current,
1663-
)
1664-
.await;
1665-
(version, res)
1666-
})
1667-
.collect::<Vec<_>>()
1668-
.await;
1661+
let data_points = db
1662+
.get_package_versions_downloads_24h(
1663+
&scope,
1664+
&package,
1665+
&recent_versions,
1666+
start,
1667+
current,
1668+
)
1669+
.await?;
16691670

1670-
let mut recent_versions = Vec::with_capacity(versions.len());
1671-
for (version, downloads) in versions {
1672-
let downloads = downloads?
1673-
.into_iter()
1674-
.map(ApiDownloadDataPoint::from)
1675-
.collect();
1676-
recent_versions
1677-
.push(ApiPackageDownloadsRecentVersion { version, downloads });
1678-
}
1671+
let mut data_points_by_version =
1672+
indexmap::IndexMap::<_, Vec<_>>::with_capacity(recent_versions.len());
1673+
1674+
for data_point in data_points {
1675+
let version = data_point.version.clone();
1676+
let downloads = data_points_by_version
1677+
.entry(version)
1678+
.or_insert_with(Vec::new);
1679+
downloads.push(ApiDownloadDataPoint::from(data_point));
1680+
}
1681+
1682+
Ok::<_, ApiError>(
1683+
data_points_by_version
1684+
.into_iter()
1685+
.map(|(version, data_points)| ApiPackageDownloadsRecentVersion {
1686+
version,
1687+
downloads: data_points,
1688+
})
1689+
.collect(),
1690+
)
1691+
};
1692+
1693+
let (total, recent_versions) =
1694+
futures::try_join!(total_fut, recent_versions_fut)?;
16791695

16801696
Ok(ApiPackageDownloads {
16811697
total: total.into_iter().map(ApiDownloadDataPoint::from).collect(),

api/src/api/types.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,16 @@ impl From<DownloadDataPoint> for ApiDownloadDataPoint {
904904
}
905905
}
906906

907+
impl From<VersionDownloadDataPoint> for ApiDownloadDataPoint {
908+
fn from(value: VersionDownloadDataPoint) -> Self {
909+
Self {
910+
time_bucket: value.time_bucket,
911+
kind: value.kind.into(),
912+
count: value.count as u64,
913+
}
914+
}
915+
}
916+
907917
#[derive(Debug, Serialize, Deserialize)]
908918
#[serde(rename_all = "snake_case")]
909919
pub enum ApiDownloadKind {

api/src/db/database.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,7 @@ impl Database {
18581858
}
18591859

18601860
#[instrument(
1861-
name = "Database::list_latest_package_versions",
1861+
name = "Database::list_latest_unyanked_versions_for_package",
18621862
skip(self),
18631863
err
18641864
)]
@@ -1874,9 +1874,11 @@ impl Database {
18741874
FROM package_versions
18751875
WHERE scope = $1 AND name = $2 AND version NOT LIKE '%-%' AND is_yanked = false
18761876
ORDER BY version DESC
1877+
LIMIT $3
18771878
"#,
18781879
scope as _,
18791880
name as _,
1881+
limit as i32,
18801882
)
18811883
.map(|r| r.version)
18821884
.fetch_all(&self.pool)
@@ -4017,25 +4019,25 @@ impl Database {
40174019
skip(self),
40184020
err
40194021
)]
4020-
pub async fn get_package_version_downloads_24h(
4022+
pub async fn get_package_versions_downloads_24h(
40214023
&self,
40224024
scope: &ScopeName,
40234025
name: &PackageName,
4024-
version: &Version,
4026+
versions: &[Version],
40254027
start: DateTime<Utc>,
40264028
end: DateTime<Utc>,
4027-
) -> Result<Vec<DownloadDataPoint>> {
4029+
) -> Result<Vec<VersionDownloadDataPoint>> {
40284030
sqlx::query_as!(
4029-
DownloadDataPoint,
4031+
VersionDownloadDataPoint,
40304032
r#"
4031-
SELECT time_bucket, kind as "kind: DownloadKind", count
4033+
SELECT version as "version: Version", time_bucket, kind as "kind: DownloadKind", count
40324034
FROM version_download_counts_24h
4033-
WHERE scope = $1 AND package = $2 AND version = $3 AND time_bucket >= $4 AND time_bucket < $5
4034-
ORDER BY time_bucket ASC
4035+
WHERE scope = $1 AND package = $2 AND version = ANY($3) AND time_bucket >= $4 AND time_bucket < $5
4036+
ORDER BY time_bucket ASC, version DESC
40354037
"#,
40364038
scope as _,
40374039
name as _,
4038-
version as _,
4040+
versions as _,
40394041
start,
40404042
end,
40414043
)

api/src/tasks.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,10 @@ mod tests {
656656

657657
// 24 hour window
658658
let downloads = db
659-
.get_package_version_downloads_24h(
659+
.get_package_versions_downloads_24h(
660660
&std,
661661
&fs,
662-
&v0_215_0,
662+
&[v0_215_0.clone()],
663663
"2024-06-01T00:00:00Z".parse().unwrap(),
664664
"2024-07-31T00:00:00Z".parse().unwrap(),
665665
)
@@ -670,13 +670,14 @@ mod tests {
670670
downloads[0].time_bucket,
671671
"2024-07-16T00:00:00Z".parse::<DateTime<Utc>>().unwrap()
672672
);
673+
assert_eq!(downloads[0].version, v0_215_0);
673674
assert_eq!(downloads[0].count, 13);
674675

675676
let downloads = db
676-
.get_package_version_downloads_24h(
677+
.get_package_versions_downloads_24h(
677678
&luca,
678679
&flag,
679-
&v1_0_0,
680+
&[v1_0_0.clone()],
680681
"2024-06-01T00:00:00Z".parse().unwrap(),
681682
"2024-07-31T00:00:00Z".parse().unwrap(),
682683
)
@@ -687,6 +688,7 @@ mod tests {
687688
downloads[0].time_bucket,
688689
"2024-07-16T00:00:00Z".parse::<DateTime<Utc>>().unwrap()
689690
);
691+
assert_eq!(downloads[0].version, v1_0_0);
690692
assert_eq!(downloads[0].count, 238);
691693
}
692694
}

frontend/routes/package/(_islands)/DownloadChart.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ function getSeries(
188188
);
189189

190190
const dataPointsToDisplay = dataPointsWithDownloads.slice(0, 5);
191-
const others = dataPointsWithDownloads.slice(5).map((dataPoints) =>
192-
dataPoints.downloads
193-
).flat();
191+
// const others = dataPointsWithDownloads.slice(5).map((dataPoints) =>
192+
// dataPoints.downloads
193+
// ).flat();
194194

195195
const xValues = collectX(
196196
dataPointsWithDownloads.map((version) => version.downloads).flat(),
@@ -202,10 +202,10 @@ function getSeries(
202202
name: version.version,
203203
data: normalize(version.downloads, xValues, aggregationPeriod),
204204
})),
205-
{
206-
name: "Other",
207-
data: normalize(others, xValues, aggregationPeriod),
208-
color: "#e7c50b", // jsr-yellow-500
209-
},
205+
// {
206+
// name: "Other",
207+
// data: normalize(others, xValues, aggregationPeriod),
208+
// color: "#e7c50b", // jsr-yellow-500
209+
// },
210210
];
211211
}

0 commit comments

Comments
 (0)