improving Snap suggestions read time

This commit is contained in:
Vinicius Moreira
2019-09-17 15:10:54 -03:00
parent 6cd682b92e
commit 80f49bd083
5 changed files with 44 additions and 20 deletions

View File

@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Improvements: ### Improvements:
- Reading installed Snaps now takes around 95% less time - Reading installed Snaps now takes around 95% less time
- Reading Snap suggestions now takes aroung 75% less time
- Reading installed Flatpaks now takes around 45% less time - Reading installed Flatpaks now takes around 45% less time
- Refreshing only the associated package type after a successful operation (install, uninstall, downgrade, ...) - Refreshing only the associated package type after a successful operation (install, uninstall, downgrade, ...)
- When a package is installed, it will be the first element of the table after refreshing - When a package is installed, it will be the first element of the table after refreshing

View File

@@ -281,7 +281,10 @@ class GenericSoftwareManager(SoftwareManager):
def _fill_suggestions(self, suggestions: list, man: SoftwareManager, limit: int): def _fill_suggestions(self, suggestions: list, man: SoftwareManager, limit: int):
if self._can_work(man): if self._can_work(man):
mti = time.time()
man_sugs = man.list_suggestions(limit) man_sugs = man.list_suggestions(limit)
mtf = time.time()
self.logger.info(man.__class__.__name__ + ' took {0:.2f} seconds'.format(mtf - mti))
if man_sugs: if man_sugs:
if len(man_sugs) > limit: if len(man_sugs) > limit:

View File

@@ -48,7 +48,7 @@ class FlatpakManager(SoftwareManager):
def search(self, words: str, disk_loader: DiskCacheLoader, limit: int = -1) -> SearchResult: def search(self, words: str, disk_loader: DiskCacheLoader, limit: int = -1) -> SearchResult:
res = SearchResult([], [], 0) res = SearchResult([], [], 0)
apps_found = flatpak.search(words) apps_found = flatpak.search(flatpak.get_version(), words)
if apps_found: if apps_found:
already_read = set() already_read = set()
@@ -189,7 +189,7 @@ class FlatpakManager(SoftwareManager):
return [self.i18n['flatpak.notification.no_remotes']] return [self.i18n['flatpak.notification.no_remotes']]
def list_suggestions(self, limit: int) -> List[PackageSuggestion]: def list_suggestions(self, limit: int) -> List[PackageSuggestion]:
cli_version = flatpak.get_version()
res = [] res = []
sugs = [(i, p) for i, p in suggestions.ALL.items()] sugs = [(i, p) for i, p in suggestions.ALL.items()]
@@ -198,7 +198,7 @@ class FlatpakManager(SoftwareManager):
for sug in sugs: for sug in sugs:
if limit <= 0 or len(res) < limit: if limit <= 0 or len(res) < limit:
app_json = flatpak.search(sug[0], app_id=True) app_json = flatpak.search(cli_version, sug[0], app_id=True)
if app_json: if app_json:
res.append(PackageSuggestion(self._map_to_model(app_json[0], False, None), sug[1])) res.append(PackageSuggestion(self._map_to_model(app_json[0], False, None), sug[1]))

View File

@@ -176,8 +176,7 @@ def get_app_commits_data(app_ref: str, origin: str) -> List[dict]:
return commits return commits
def search(word: str, app_id: bool = False) -> List[dict]: def search(version: str, word: str, app_id: bool = False) -> List[dict]:
cli_version = get_version()
res = run_cmd('{} search {}'.format(BASE_CMD, word)) res = run_cmd('{} search {}'.format(BASE_CMD, word))
@@ -189,39 +188,39 @@ def search(word: str, app_id: bool = False) -> List[dict]:
for info in split_res: for info in split_res:
if info: if info:
info_list = info.split('\t') info_list = info.split('\t')
if cli_version >= '1.3.0': if version >= '1.3.0':
id_ = info_list[2].strip() id_ = info_list[2].strip()
if app_id and id_ != word: if app_id and id_ != word:
continue continue
version = info_list[3].strip() pkg_ver = info_list[3].strip()
app = { app = {
'name': info_list[0].strip(), 'name': info_list[0].strip(),
'description': info_list[1].strip(), 'description': info_list[1].strip(),
'id': id_, 'id': id_,
'version': version, 'version': pkg_ver,
'latest_version': version, 'latest_version': pkg_ver,
'branch': info_list[4].strip(), 'branch': info_list[4].strip(),
'origin': info_list[5].strip(), 'origin': info_list[5].strip(),
'runtime': False, 'runtime': False,
'arch': None, # unknown at this moment, 'arch': None, # unknown at this moment,
'ref': None # unknown at this moment 'ref': None # unknown at this moment
} }
elif cli_version >= '1.2.0': elif version >= '1.2.0':
id_ = info_list[1].strip() id_ = info_list[1].strip()
if app_id and id_ != word: if app_id and id_ != word:
continue continue
desc = info_list[0].split('-') desc = info_list[0].split('-')
version = info_list[2].strip() pkg_ver = info_list[2].strip()
app = { app = {
'name': desc[0].strip(), 'name': desc[0].strip(),
'description': desc[1].strip(), 'description': desc[1].strip(),
'id': id_, 'id': id_,
'version': version, 'version': pkg_ver,
'latest_version': version, 'latest_version': pkg_ver,
'branch': info_list[3].strip(), 'branch': info_list[3].strip(),
'origin': info_list[4].strip(), 'origin': info_list[4].strip(),
'runtime': False, 'runtime': False,
@@ -234,13 +233,13 @@ def search(word: str, app_id: bool = False) -> List[dict]:
if app_id and id_ != word: if app_id and id_ != word:
continue continue
version = info_list[1].strip() pkg_ver = info_list[1].strip()
app = { app = {
'name': '', 'name': '',
'description': info_list[4].strip(), 'description': info_list[4].strip(),
'id': id_, 'id': id_,
'version': version, 'version': pkg_ver,
'latest_version': version, 'latest_version': pkg_ver,
'branch': info_list[2].strip(), 'branch': info_list[2].strip(),
'origin': info_list[3].strip(), 'origin': info_list[3].strip(),
'runtime': False, 'runtime': False,

View File

@@ -1,12 +1,15 @@
from datetime import datetime from datetime import datetime
from threading import Thread
from typing import List, Set, Type from typing import List, Set, Type
from bauh.api.abstract.controller import SoftwareManager, SearchResult, ApplicationContext from bauh.api.abstract.controller import SoftwareManager, SearchResult, ApplicationContext
from bauh.api.abstract.disk import DiskCacheLoader from bauh.api.abstract.disk import DiskCacheLoader
from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.handler import ProcessWatcher
from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpdate, PackageSuggestion from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpdate, PackageSuggestion, \
SuggestionPriority
from bauh.commons.system import SystemProcess, ProcessHandler from bauh.commons.system import SystemProcess, ProcessHandler
from bauh.gems.snap import snap, suggestions from bauh.gems.snap import snap, suggestions
from bauh.gems.snap.constants import SNAP_API_URL
from bauh.gems.snap.model import SnapApplication from bauh.gems.snap.model import SnapApplication
from bauh.gems.snap.worker import SnapAsyncDataLoader from bauh.gems.snap.worker import SnapAsyncDataLoader
@@ -19,6 +22,8 @@ class SnapManager(SoftwareManager):
self.api_cache = context.cache_factory.new() self.api_cache = context.cache_factory.new()
context.disk_loader_factory.map(SnapApplication, self.api_cache) context.disk_loader_factory.map(SnapApplication, self.api_cache)
self.enabled = True self.enabled = True
self.http_client = context.http_client
self.logger = context.logger
def map_json(self, app_json: dict, installed: bool, disk_loader: DiskCacheLoader) -> SnapApplication: def map_json(self, app_json: dict, installed: bool, disk_loader: DiskCacheLoader) -> SnapApplication:
app = SnapApplication(publisher=app_json.get('publisher'), app = SnapApplication(publisher=app_json.get('publisher'),
@@ -133,19 +138,35 @@ class SnapManager(SoftwareManager):
if snap.get_snapd_version() == 'unavailable': if snap.get_snapd_version() == 'unavailable':
return [self.i18n['snap.notification.snapd_unavailable']] return [self.i18n['snap.notification.snapd_unavailable']]
def _fill_suggestion(self, pkg_name: str, priority: SuggestionPriority, out: List[PackageSuggestion]):
res = self.http_client.get_json(SNAP_API_URL + '/search?q=package_name:{}'.format(pkg_name))
if res and res['_embedded']['clickindex:package']:
pkg = res['_embedded']['clickindex:package'][0]
pkg['rev'] = pkg['revision']
pkg['name'] = pkg_name
out.append(PackageSuggestion(self.map_json(pkg, installed=False, disk_loader=None), priority))
else:
self.logger.warning("Could not retrieve suggestion '{}'".format(pkg_name))
def list_suggestions(self, limit: int) -> List[PackageSuggestion]: def list_suggestions(self, limit: int) -> List[PackageSuggestion]:
res = [] res = []
sugs = [(i, p) for i, p in suggestions.ALL.items()] sugs = [(i, p) for i, p in suggestions.ALL.items()]
sugs.sort(key=lambda t: t[1].value, reverse=True) sugs.sort(key=lambda t: t[1].value, reverse=True)
threads = []
for sug in sugs: for sug in sugs:
if limit <= 0 or len(res) < limit: if limit <= 0 or len(res) < limit:
found = snap.search(sug[0], exact_name=True) t = Thread(target=self._fill_suggestion, args=(sug[0], sug[1], res))
if found: t.start()
res.append(PackageSuggestion(self.map_json(found[0], installed=False, disk_loader=None), sug[1])) threads.append(t)
else: else:
break break
for t in threads:
t.join()
return res return res