Skip to content

Commit cf7bc18

Browse files
perf: improve the efficiency of a core function
Implemented by the rabbit, it looks good to me cause it's essentially a Promise.all in the middle of what I was originally doing, it looks like nothing broke, let's wish it's indeed the case. Resolves #62
1 parent 0d9e9a3 commit cf7bc18

File tree

1 file changed

+60
-30
lines changed

1 file changed

+60
-30
lines changed

src/routes/package/releases.ts

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,40 @@ export async function getPackageReleases(
2828
const foundVersions = new Set<string>();
2929
const releases: ({ cleanName: string; cleanVersion: string } & GitHubRelease)[] = [];
3030

31-
// Discover releases
3231
console.log("Starting loading releases...");
32+
33+
// Step 1: First identify all matching packages and create fetch tasks
34+
const matchingPackageTasks: {
35+
category: Repository["category"];
36+
repo: (typeof allPackages)[number]["packages"][number];
37+
releasesFetch: () => Promise<GitHubRelease[]>;
38+
}[] = [];
39+
40+
// Collect all matching packages and create fetch tasks
3341
for (const { category, packages } of allPackages) {
3442
for (const { pkg, ...repo } of packages) {
3543
if (pkg.name.localeCompare(packageName, undefined, { sensitivity: "base" }) !== 0) continue;
3644

37-
// 1. Get releases
38-
const cachedReleases = await githubCache.getReleases({ ...repo, category });
45+
matchingPackageTasks.push({
46+
category,
47+
repo: { pkg, ...repo },
48+
// Create a fetch task but don't await it yet
49+
releasesFetch: () => githubCache.getReleases({ ...repo, category })
50+
});
51+
}
52+
}
53+
54+
// Step 2: Process all fetch tasks in parallel
55+
const taskResults = await Promise.all(
56+
matchingPackageTasks.map(async ({ category, repo, releasesFetch }) => {
57+
// Await the individual fetch and process its results
58+
const cachedReleases = await releasesFetch();
59+
3960
console.log(
4061
`${cachedReleases.length} releases found for repo ${repo.repoOwner}/${repo.repoName}`
4162
);
4263

43-
// 2. Filter out invalid ones
64+
// Filter out invalid releases and sort them
4465
const validReleases = cachedReleases
4566
.map(release => {
4667
if (!release.tag_name && release.name) return { ...release, tag_name: release.name }; // Mitigate (?) some obscure empty tags scenarios
@@ -60,7 +81,7 @@ export async function getPackageReleases(
6081
const [name] = repo.metadataFromTag(release.tag_name);
6182
return (
6283
(repo.dataFilter?.(release) ?? true) &&
63-
pkg.name.localeCompare(name, undefined, { sensitivity: "base" }) === 0
84+
repo.pkg.name.localeCompare(name, undefined, { sensitivity: "base" }) === 0
6485
);
6586
})
6687
.sort((a, b) => {
@@ -70,33 +91,42 @@ export async function getPackageReleases(
7091
});
7192
console.log("Final filtered count:", validReleases.length);
7293

73-
// 3. For each release, check if it is already found, searching by versions
74-
const { dataFilter, metadataFromTag, changelogContentsReplacer, ...rest } = repo;
75-
for (const release of validReleases) {
76-
const [cleanName, cleanVersion] = repo.metadataFromTag(release.tag_name);
77-
console.log(`Release ${release.tag_name}, extracted version: ${cleanVersion}`);
78-
if (foundVersions.has(cleanVersion)) continue;
79-
80-
// If not, add its version to the set and itself to the final version
81-
const currentNewestVersion = [...foundVersions].sort(semver.rcompare)[0];
82-
console.log("Current newest version", currentNewestVersion);
83-
foundVersions.add(cleanVersion);
84-
releases.push({ cleanName, cleanVersion, ...release });
85-
86-
// If it is newer than the newest we got, set this repo as the "final repo"
87-
if (!currentNewestVersion || semver.gt(cleanVersion, currentNewestVersion)) {
88-
console.log(
89-
`Current newest version "${currentNewestVersion}" doesn't exist or is lesser than ${cleanVersion}, setting ${repo.repoOwner}/${repo.repoName} as final repo`
90-
);
91-
currentPackage = {
92-
category,
93-
pkg,
94-
...rest
95-
};
96-
}
94+
// Return the processed data for further processing
95+
return {
96+
category,
97+
repo,
98+
validReleases
99+
};
100+
})
101+
);
102+
103+
// Step 3: Process all results sequentially to maintain consistent result
104+
for (const { category, repo, validReleases } of taskResults) {
105+
// For each release, check if it is already found, searching by versions
106+
const { dataFilter, metadataFromTag, changelogContentsReplacer, ...serializableRepo } = repo;
107+
for (const release of validReleases) {
108+
const [cleanName, cleanVersion] = repo.metadataFromTag(release.tag_name);
109+
console.log(`Release ${release.tag_name}, extracted version: ${cleanVersion}`);
110+
if (foundVersions.has(cleanVersion)) continue;
111+
112+
// If not, add its version to the set and itself to the final version
113+
const currentNewestVersion = [...foundVersions].sort(semver.rcompare)[0];
114+
console.log("Current newest version", currentNewestVersion);
115+
foundVersions.add(cleanVersion);
116+
releases.push({ cleanName, cleanVersion, ...release });
117+
118+
// If it is newer than the newest we got, set this repo as the "final repo"
119+
if (!currentNewestVersion || semver.gt(cleanVersion, currentNewestVersion)) {
120+
console.log(
121+
`Current newest version "${currentNewestVersion}" doesn't exist or is lesser than ${cleanVersion}, setting ${repo.repoOwner}/${repo.repoName} as final repo`
122+
);
123+
currentPackage = {
124+
category,
125+
...serializableRepo
126+
};
97127
}
98-
console.log("Done");
99128
}
129+
console.log("Done");
100130
}
101131

102132
return currentPackage

0 commit comments

Comments
 (0)