mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 23:37:18 +00:00
do not spawn process for single architecture run
This commit is contained in:
parent
60246dd833
commit
74b18ff3e5
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user