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.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitecture
from ahriman.core.exceptions import MissingArchitecture, MultipleArchitecture
from ahriman.models.repository_paths import RepositoryPaths
class Handler:
"""
base handler class for command callbacks
:cvar ALLOW_MULTI_ARCHITECTURE_RUN: allow to run with multiple architectures
"""
ALLOW_MULTI_ARCHITECTURE_RUN = True
@classmethod
def _call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool:
"""
@ -61,9 +64,18 @@ class Handler:
:return: 0 on success, 1 otherwise
"""
architectures = cls.extract_architectures(args)
with Pool(len(architectures)) as pool:
result = pool.starmap(
cls._call, [(args, architecture) for architecture in architectures])
# 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:
result = pool.starmap(
cls._call, [(args, architecture) for architecture in architectures])
else:
result = [cls._call(args, architectures.pop())]
return 0 if all(result) else 1
@classmethod

View File

@ -31,6 +31,8 @@ class Web(Handler):
web server handler
"""
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
@classmethod
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
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")
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):
"""
report generation exception

View File

@ -6,7 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Handler
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:
@ -44,6 +44,29 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
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:
"""
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)
setup_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