diff --git a/bauh/api/abstract/disk.py b/bauh/api/abstract/disk.py index 82b785a9..bcac5792 100644 --- a/bauh/api/abstract/disk.py +++ b/bauh/api/abstract/disk.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Type +from typing import Type, Optional, Any, Dict from bauh.api.abstract.cache import MemoryCache from bauh.api.abstract.model import SoftwarePackage @@ -29,6 +29,12 @@ class DiskCacheLoader: """ pass + def read(self, pkg: SoftwarePackage) -> Optional[Dict[str, Any]]: + """ + returns the cached data from the given package + """ + pass + class DiskCacheLoaderFactory(ABC): diff --git a/bauh/gems/arch/controller.py b/bauh/gems/arch/controller.py index 757aa766..22a66838 100644 --- a/bauh/gems/arch/controller.py +++ b/bauh/gems/arch/controller.py @@ -3714,6 +3714,17 @@ class ArchManager(SoftwareManager, SettingsController): if suggestions: output.update(suggestions) + def _fill_cached_if_unset(self, pkg: ArchPackage, loader: DiskCacheLoader): + data = loader.read(pkg) + + if data: + for attr, cached_val in data.items(): + if cached_val: + current_val = getattr(pkg, attr) + + if current_val is None: + setattr(pkg, attr, cached_val) + def list_suggestions(self, limit: int, filter_installed: bool) -> Optional[List[PackageSuggestion]]: if limit == 0: return [] @@ -3791,6 +3802,11 @@ class ArchManager(SoftwareManager, SettingsController): if full_data and full_data.get('signed'): full_data = full_data['signed'] + disk_loader, caching_threads = None, None + if not filter_installed: + disk_loader = self.context.disk_loader_factory.new() + caching_threads = list() + suggestions = [] for name in suggestion_by_priority: pkg_data = available_suggestions[name] @@ -3801,18 +3817,27 @@ class ArchManager(SoftwareManager, SettingsController): description = pkg_full_data.get('description') pkg_updates_ignored = pkg_data['i'] and ignored_updates and name in ignored_updates + pkg = ArchPackage(name=name, + version=pkg_data['v'], + latest_version=pkg_data['v'], + repository=pkg_data['r'], + installed=pkg_data['i'], + description=description, + categories=self.categories.get(name), + i18n=self.i18n, + maintainer=pkg_data['r'], + update_ignored=pkg_updates_ignored) - suggestions.append(PackageSuggestion(package=ArchPackage(name=name, - version=pkg_data['v'], - latest_version=pkg_data['v'], - repository=pkg_data['r'], - installed=pkg_data['i'], - description=description, - categories=self.categories.get(name), - i18n=self.i18n, - maintainer=pkg_data['r'], - update_ignored=pkg_updates_ignored), - priority=name_priority[name])) + if disk_loader: + t = Thread(target=self._fill_cached_if_unset, args=(pkg, disk_loader)) + t.start() + caching_threads.append(t) + + suggestions.append(PackageSuggestion(package=pkg, priority=name_priority[name])) + + if caching_threads: + for t in caching_threads: + t.join() return suggestions diff --git a/bauh/view/util/disk.py b/bauh/view/util/disk.py index 786ed4e0..76fd78ab 100644 --- a/bauh/view/util/disk.py +++ b/bauh/view/util/disk.py @@ -3,7 +3,7 @@ import logging import os import time from threading import Thread, Lock -from typing import Type, Dict +from typing import Type, Dict, Any, Optional import yaml @@ -37,6 +37,22 @@ class AsyncDiskCacheLoader(Thread, DiskCacheLoader): else: self.pkgs.append(pkg) + def read(self, pkg: SoftwarePackage) -> Optional[Dict[str, Any]]: + if pkg and pkg.supports_disk_cache() and os.path.exists(pkg.get_disk_cache_path()): + disk_path = pkg.get_disk_data_path() + ext = disk_path.split('.')[-1] + + with open(disk_path) as f: + if ext == 'json': + cached_data = json.loads(f.read()) + elif ext in {'yml', 'yaml'}: + cached_data = yaml.load(f.read()) + else: + raise Exception(f'The cached data file {disk_path} has an unsupported format') + + if cached_data: + return cached_data + def stop_working(self): self._work = False @@ -58,26 +74,16 @@ class AsyncDiskCacheLoader(Thread, DiskCacheLoader): self._working = False def _fill_cached_data(self, pkg: SoftwarePackage) -> bool: - if os.path.exists(pkg.get_disk_data_path()): - disk_path = pkg.get_disk_data_path() - ext = disk_path.split('.')[-1] + cached_data = self.read(pkg) - with open(disk_path) as f: - if ext == 'json': - cached_data = json.loads(f.read()) - elif ext in {'yml', 'yaml'}: - cached_data = yaml.load(f.read()) - else: - raise Exception('The cached data file {} has an unsupported format'.format(disk_path)) + if cached_data: + pkg.fill_cached_data(cached_data) + cache = self.cache_map.get(pkg.__class__) - if cached_data: - pkg.fill_cached_data(cached_data) - cache = self.cache_map.get(pkg.__class__) + if cache: + cache.add_non_existing(str(pkg.id), cached_data) - if cache: - cache.add_non_existing(str(pkg.id), cached_data) - - return True + return True return False