do not spawn process for single architecture run

This commit is contained in:
Evgenii Alekseev 2021-09-08 23:47:29 +03:00
parent 60246dd833
commit 74b18ff3e5
5 changed files with 62 additions and 5 deletions

View File

@ -27,15 +27,18 @@ from typing import Set, Type
from ahriman.application.lock import Lock from ahriman.application.lock import Lock
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitecture from ahriman.core.exceptions import MissingArchitecture, MultipleArchitecture
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
class Handler: class Handler:
""" """
base handler class for command callbacks base handler class for command callbacks
:cvar ALLOW_MULTI_ARCHITECTURE_RUN: allow to run with multiple architectures
""" """
ALLOW_MULTI_ARCHITECTURE_RUN = True
@classmethod @classmethod
def _call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool: def _call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool:
""" """
@ -61,9 +64,18 @@ class Handler:
:return: 0 on success, 1 otherwise :return: 0 on success, 1 otherwise
""" """
architectures = cls.extract_architectures(args) architectures = cls.extract_architectures(args)
# actually we do not have to spawn another process if it is single-process application, do we?
if len(architectures) > 1:
if not cls.ALLOW_MULTI_ARCHITECTURE_RUN:
raise MultipleArchitecture(args.command)
with Pool(len(architectures)) as pool: with Pool(len(architectures)) as pool:
result = pool.starmap( result = pool.starmap(
cls._call, [(args, architecture) for architecture in architectures]) cls._call, [(args, architecture) for architecture in architectures])
else:
result = [cls._call(args, architectures.pop())]
return 0 if all(result) else 1 return 0 if all(result) else 1
@classmethod @classmethod

View File

@ -31,6 +31,8 @@ class Web(Handler):
web server handler web server handler
""" """
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
@classmethod @classmethod
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
configuration: Configuration, no_report: bool) -> None: configuration: Configuration, no_report: bool) -> None:

View File

@ -109,6 +109,19 @@ class MissingArchitecture(Exception):
Exception.__init__(self, f"Architecture required for subcommand {command}, but missing") Exception.__init__(self, f"Architecture required for subcommand {command}, but missing")
class MultipleArchitecture(Exception):
"""
exception which will be raised if multiple architectures are not supported by the handler
"""
def __init__(self, command: str) -> None:
"""
default constructor
:param command: command name which throws exception
"""
Exception.__init__(self, f"Multiple architectures are not supported by subcommand {command}")
class ReportFailed(Exception): class ReportFailed(Exception):
""" """
report generation exception report generation exception

View File

@ -6,7 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitecture from ahriman.core.exceptions import MissingArchitecture, MultipleArchitecture
def test_call(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_call(args: argparse.Namespace, mocker: MockerFixture) -> None:
@ -44,6 +44,29 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
starmap_mock.assert_called_once() starmap_mock.assert_called_once()
def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise an exception if multiple architectures are not supported by the handler
"""
args.architecture = ["i686", "x86_64"]
args.command = "web"
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecture):
Handler.execute(args)
def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in current process if only one architecture supplied
"""
args.architecture = ["x86_64"]
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args)
starmap_mock.assert_not_called()
def test_extract_architectures(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_extract_architectures(args: argparse.Namespace, mocker: MockerFixture) -> None:
""" """
must generate list of available architectures must generate list of available architectures

View File

@ -29,3 +29,10 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
Web.run(args, "x86_64", configuration, True) Web.run(args, "x86_64", configuration, True)
setup_mock.assert_called_once() setup_mock.assert_called_once()
run_mock.assert_called_once() run_mock.assert_called_once()
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Web.ALLOW_MULTI_ARCHITECTURE_RUN