From 783edfd3b200ac435b6f166b2a6649f37500126c Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Sat, 30 Dec 2023 17:00:24 +0200 Subject: [PATCH] suppress erros while retrieving worker list --- .../core/distributed/distributed_system.py | 31 +++++++++++++------ .../core/distributed/worker_loader_trigger.py | 3 ++ .../distributed/test_distributed_system.py | 18 ++++++++++- .../distributed/test_worker_loader_trigger.py | 13 ++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/ahriman/core/distributed/distributed_system.py b/src/ahriman/core/distributed/distributed_system.py index 7ed059e0..b5bf9b50 100644 --- a/src/ahriman/core/distributed/distributed_system.py +++ b/src/ahriman/core/distributed/distributed_system.py @@ -17,10 +17,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # +import contextlib import tempfile import uuid from pathlib import Path +from functools import cached_property from ahriman.core.configuration import Configuration from ahriman.core.configuration.schema import ConfigurationSchema @@ -36,7 +38,6 @@ class DistributedSystem(Trigger, WebClient): Attributes: identifier_path(Path): path to cached worker identifier - worker(Worker): unique self identifier """ CONFIGURATION_SCHEMA: ConfigurationSchema = { @@ -77,8 +78,17 @@ class DistributedSystem(Trigger, WebClient): section, "identifier_path", fallback=Path(tempfile.gettempdir()) / "ahriman-worker-identifier") self._owe_identifier = False - identifier = self.load_identifier(configuration, section) - self.worker = Worker(configuration.get(section, "address"), identifier=identifier) + @cached_property + def worker(self) -> Worker: + """ + load and set worker. Lazy property loaded because it is not always required + + Returns: + Worker: unique self worker identifier + """ + section = next(iter(self.configuration_sections(self.configuration))) + identifier = self.load_identifier(self.configuration, section) + return Worker(self.configuration.get(section, "address"), identifier=identifier) @classmethod def configuration_sections(cls, configuration: Configuration) -> list[str]: @@ -161,10 +171,13 @@ class DistributedSystem(Trigger, WebClient): Returns: list[Worker]: currently registered workers """ - response = self.make_request("GET", self._workers_url()) - response_json = response.json() + with contextlib.suppress(Exception): + response = self.make_request("GET", self._workers_url()) + response_json = response.json() - return [ - Worker(worker["address"], identifier=worker["identifier"]) - for worker in response_json - ] + return [ + Worker(worker["address"], identifier=worker["identifier"]) + for worker in response_json + ] + + return [] diff --git a/src/ahriman/core/distributed/worker_loader_trigger.py b/src/ahriman/core/distributed/worker_loader_trigger.py index f04fcd01..cd30095c 100644 --- a/src/ahriman/core/distributed/worker_loader_trigger.py +++ b/src/ahriman/core/distributed/worker_loader_trigger.py @@ -33,5 +33,8 @@ class WorkerLoaderTrigger(DistributedSystem): return # there is manually set option workers = [worker.address for worker in self.workers()] + if not workers: + return + self.logger.info("load workers %s", workers) self.configuration.set_option("build", "workers", " ".join(workers)) diff --git a/tests/ahriman/core/distributed/test_distributed_system.py b/tests/ahriman/core/distributed/test_distributed_system.py index d5c8e9f1..e6aaf93e 100644 --- a/tests/ahriman/core/distributed/test_distributed_system.py +++ b/tests/ahriman/core/distributed/test_distributed_system.py @@ -159,7 +159,7 @@ def test_unregister_force(distributed_system: DistributedSystem, mocker: MockerF remove_mock.assert_called_once_with(missing_ok=True) -def test_workers_get(distributed_system: DistributedSystem, mocker: MockerFixture) -> None: +def test_workers(distributed_system: DistributedSystem, mocker: MockerFixture) -> None: """ must return available remote workers """ @@ -174,3 +174,19 @@ def test_workers_get(distributed_system: DistributedSystem, mocker: MockerFixtur result = distributed_system.workers() requests_mock.assert_called_once_with("GET", distributed_system._workers_url()) assert result == [worker] + + +def test_workers_failed(distributed_system: DistributedSystem, mocker: MockerFixture) -> None: + """ + must suppress any exception happened during worker extraction + """ + mocker.patch("requests.Session.request", side_effect=Exception()) + distributed_system.workers() + + +def test_workers_failed_http_error(distributed_system: DistributedSystem, mocker: MockerFixture) -> None: + """ + must suppress HTTP exception happened during worker extraction + """ + mocker.patch("requests.Session.request", side_effect=requests.HTTPError()) + distributed_system.workers() diff --git a/tests/ahriman/core/distributed/test_worker_loader_trigger.py b/tests/ahriman/core/distributed/test_worker_loader_trigger.py index 7a1200da..b5b261a9 100644 --- a/tests/ahriman/core/distributed/test_worker_loader_trigger.py +++ b/tests/ahriman/core/distributed/test_worker_loader_trigger.py @@ -32,3 +32,16 @@ def test_on_start_skip(configuration: Configuration, mocker: MockerFixture) -> N trigger = WorkerLoaderTrigger(repository_id, configuration) trigger.on_start() run_mock.assert_not_called() + + +def test_on_start_empty_list(configuration: Configuration, mocker: MockerFixture) -> None: + """ + must do not set anything if workers are not available + """ + configuration.set_option("status", "address", "http://localhost:8081") + mocker.patch("ahriman.core.distributed.WorkerLoaderTrigger.workers", return_value=[]) + _, repository_id = configuration.check_loaded() + + trigger = WorkerLoaderTrigger(repository_id, configuration) + trigger.on_start() + assert not configuration.has_option("build", "workers")