Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit c5decfa

Browse files
getneilneil molina
andauthored
optimize packagesList filtering: (#551)
* optimize packagesList filtering: - implement initial sorting by last_modified_at date - queue retrieval of bottles data * cleanup --------- Co-authored-by: neil molina <neil@neils-MacBook-Pro.local>
1 parent 7f7efdf commit c5decfa

3 files changed

Lines changed: 74 additions & 38 deletions

File tree

modules/desktop/src/components/packages/packages.svelte

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
const { packageList: allPackages } = packagesStore;
1616
export let packageFilter: SideMenuOptions = SideMenuOptions.all;
1717
18-
export let sortBy: "popularity" | "most recent" = "most recent";
19-
export let sortDirection: "asc" | "desc" = "desc";
20-
2118
export let scrollY = 0;
2219
2320
let loadMore = 9;
@@ -43,14 +40,6 @@
4340
[SideMenuOptions.new_packages]: (pkg: GUIPackage) => {
4441
return moment(pkg.created).isAfter(moment().subtract(30, "days"));
4542
},
46-
[SideMenuOptions.popular]: (pkg: GUIPackage) =>
47-
pkg.categories.includes(SideMenuOptions.popular),
48-
[SideMenuOptions.featured]: (pkg: GUIPackage) =>
49-
pkg.categories.includes(SideMenuOptions.featured),
50-
[SideMenuOptions.essentials]: (pkg: GUIPackage) =>
51-
pkg.categories.includes(SideMenuOptions.essentials),
52-
[SideMenuOptions.starstruck]: (pkg: GUIPackage) =>
53-
pkg.categories.includes(SideMenuOptions.starstruck),
5443
[SideMenuOptions.made_by_tea]: (pkg: GUIPackage) => pkg.full_name.includes("tea.xyz")
5544
};
5645
@@ -59,18 +48,7 @@
5948
scrollY = target.scrollTop || 0;
6049
};
6150
62-
$: packages = $allPackages.filter(pkgFilters[packageFilter] || pkgFilters.all).sort((a, b) => {
63-
if (sortBy === "popularity") {
64-
const aPop = +a.dl_count + a.installs;
65-
const bPop = +b.dl_count + b.installs;
66-
return sortDirection === "asc" ? aPop - bPop : bPop - aPop;
67-
} else {
68-
// most recent
69-
const aDate = new Date(a.last_modified);
70-
const bDate = new Date(b.last_modified);
71-
return sortDirection === "asc" ? +aDate - +bDate : +bDate - +aDate;
72-
}
73-
});
51+
$: packages = $allPackages.filter(pkgFilters[packageFilter] || pkgFilters.all);
7452
7553
const onResize = (node: HTMLElement) => {
7654
const assumedCardHeight = 250;

modules/desktop/src/libs/stores/pkgs.ts

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,28 @@ export default function initPackagesStore() {
3737
let refreshTimeoutId: ReturnType<typeof setTimeout> | null = null;
3838

3939
const packageMap = writable<Packages>({ version: "0", packages: {} });
40-
const packageList = derived(packageMap, ($packages) => Object.values($packages.packages));
40+
const packageList = derived(packageMap, ($packages) =>
41+
Object.values($packages.packages).sort((a, b) => {
42+
// implement default sort by last_modified > descending
43+
const aDate = new Date(a.last_modified);
44+
const bDate = new Date(b.last_modified);
45+
return +bDate - +aDate;
46+
})
47+
);
4148

4249
let packagesIndex: Fuse<GUIPackage>;
4350

51+
// TODO: derive this concurrency relative to user's internet and computer performance?
52+
const concurrency = 3;
53+
const bottlesQueue = new Queue(concurrency, []);
54+
bottlesQueue.setProcessor(async (pkgName: string) => {
55+
// TODO: this api should take an architecture argument or else an architecture filter should be applied downstreawm
56+
const bottles = await getPackageBottles(pkgName);
57+
if (bottles?.length) {
58+
updatePackage(pkgName, { bottles });
59+
}
60+
});
61+
4462
const updateAllPackages = (guiPkgs: GUIPackage[]) => {
4563
packageMap.update((pkgs) => {
4664
guiPkgs.forEach((pkg) => {
@@ -266,11 +284,7 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
266284
};
267285

268286
const fetchPackageBottles = async (pkgName: string) => {
269-
// TODO: this api should take an architecture argument or else an architecture filter should be applied downstreawm
270-
const bottles = await getPackageBottles(pkgName);
271-
if (bottles?.length) {
272-
updatePackage(pkgName, { bottles });
273-
}
287+
bottlesQueue.enqueue(pkgName);
274288
};
275289

276290
const deletePkg = async (pkg: GUIPackage, version: string) => {
@@ -366,3 +380,55 @@ const setBadgeCountFromPkgs = (pkgs: Packages) => {
366380
log.error(error);
367381
}
368382
};
383+
384+
type Processor = (input: string) => void;
385+
386+
// TODO: move this to a generic design pattern then to another module
387+
class Queue {
388+
private items: string[] = [];
389+
private processor: Processor | null = null;
390+
private processingCount = 0;
391+
private concurrency: number;
392+
393+
constructor(concurrency = 3, initialItems: string[] = []) {
394+
this.concurrency = concurrency;
395+
this.items = initialItems;
396+
}
397+
398+
setProcessor(processor: Processor): void {
399+
this.processor = processor;
400+
}
401+
402+
private async processQueue(): Promise<void> {
403+
if (this.processingCount >= this.concurrency || this.items.length === 0 || !this.processor) {
404+
return;
405+
}
406+
407+
const item = this.dequeue();
408+
if (item !== undefined) {
409+
this.processingCount++;
410+
Promise.resolve(this.processor(item))
411+
.then(() => {
412+
this.processingCount--;
413+
this.processQueue();
414+
})
415+
.catch((error) => {
416+
console.error(`Error processing item: ${error}`);
417+
this.processingCount--;
418+
this.processQueue();
419+
});
420+
421+
// Start processing the next item(s) if concurrency allows
422+
this.processQueue();
423+
}
424+
}
425+
426+
enqueue(item: string): void {
427+
this.items.push(item);
428+
this.processQueue();
429+
}
430+
431+
dequeue(): string | undefined {
432+
return this.items.shift();
433+
}
434+
}

modules/desktop/src/routes/+page.svelte

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
2222
let sideMenuOption = (url.searchParams.get("tab") as SideMenuOptions) || SideMenuOptions.discover;
2323
24-
let sortBy: "popularity" | "most recent" = "most recent";
25-
let sortDirection: "asc" | "desc" = "desc";
26-
2724
let updating = false;
2825
2926
let packagesScrollY = 0;
@@ -64,12 +61,7 @@
6461
{#if sideMenuOption == SideMenuOptions.discover}
6562
<DiscoverPackages bind:scrollY={packagesScrollY} />
6663
{:else}
67-
<Packages
68-
packageFilter={sideMenuOption}
69-
{sortBy}
70-
{sortDirection}
71-
bind:scrollY={packagesScrollY}
72-
/>
64+
<Packages packageFilter={sideMenuOption} bind:scrollY={packagesScrollY} />
7365
{/if}
7466
</ul>
7567
<header class="z-30 flex items-center justify-between" class:scrolling={packagesScrollY > 150}>

0 commit comments

Comments
 (0)