From 0483de2e23368bdd2b869d82af36d6e2b59a0869 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 30 Jul 2024 14:06:00 +0200 Subject: [PATCH] Filtered out 'bad' mirrors. Also added a sorting mechanism that uses the mirrors 'score' rather than just the URL name. This will emulate the reflector.service/rankmirrors behavior and thus reducing the need to re-rank the mirrors. --- archinstall/lib/mirrors.py | 49 +++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 65c85a2c79..138b9d433b 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -8,7 +8,7 @@ from .networking import fetch_data_from_url from .output import warn, FormattedOutput from .storage import storage -from .models.mirrors import MirrorStatusListV3 +from .models.mirrors import MirrorStatusListV3, MirrorStatusEntryV3 if TYPE_CHECKING: _: Any @@ -282,23 +282,43 @@ def select_custom_mirror(prompt: str = '', preset: List[CustomMirror] = []): return custom_mirrors -def _parse_mirror_list(mirrorlist: str) -> Dict[str, List[str]]: +def sort_mirror_list(mirror_list :List[MirrorStatusEntryV3], sorting_element :str = "url") -> List[MirrorStatusEntryV3]: + return sorted(mirror_list, key=lambda item: getattr(item, sorting_element)) + + +def _parse_mirror_list(mirrorlist: str, sorting_element :str = "url") -> Dict[str, List[str]]: mirror_status = MirrorStatusListV3(**json.loads(mirrorlist)) - mirror_list: Dict[str, List[str]] = {} + sorting_placeholder: Dict[str, List[MirrorStatusEntryV3]] = {} for mirror in mirror_status.urls: + # We filter out mirrors that have bad criteria values + if any([ + mirror.active is False, # Disabled by mirror-list admins + mirror.last_sync is None, # Has not synced recently + # mirror.score (error rate) over time reported from backend: https://github.com/archlinux/archweb/blob/31333d3516c91db9a2f2d12260bd61656c011fd1/mirrors/utils.py#L111C22-L111C66 + (mirror.score is None or mirror.score >= 100), + ]): + continue + + if mirror.country == "": + # TODO: This should be removed once RFC!29 is merged and completed + # Until then, there are mirrors which lacks data in the backend + # and there is no way of knowing where they're located. + # So we have to assume world-wide + mirror.country = "Worldwide" + if mirror.url.startswith('http'): - if mirror.country == "": - # TODO: This should be removed once RFC!29 is merged and completed - # Until then, there are mirrors which lacks data in the backend - # and there is no way of knowing where they're located. - # So we have to assume world-wide - mirror.country = "Worldwide" + sorting_placeholder.setdefault(mirror.country, []).append(mirror) - mirror_list.setdefault(mirror.country, []).append(mirror.url) + sorted_by_element: Dict[str, List[str]] = dict({ + region: [ + mirror.url for mirror in sort_mirror_list(unsorted_mirrors, sorting_element=sorting_element) + ] + for region, unsorted_mirrors in sorted(sorting_placeholder.items(), key=lambda item: item[0]) + }) - return mirror_list + return sorted_by_element def list_mirrors() -> Dict[str, List[str]]: @@ -315,9 +335,4 @@ def list_mirrors() -> Dict[str, List[str]]: warn(f'Could not fetch an active mirror-list: {err}') return regions - regions = _parse_mirror_list(mirrorlist) - sorted_regions = {} - for region, urls in regions.items(): - sorted_regions[region] = sorted(urls, reverse=True) - - return sorted_regions + return _parse_mirror_list(mirrorlist, sorting_element="score") \ No newline at end of file