@@ -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+ }
0 commit comments