diff --git a/docs/source/installation/guide_complete.rst b/docs/source/installation/guide_complete.rst index 49136bbba7..764274616d 100644 --- a/docs/source/installation/guide_complete.rst +++ b/docs/source/installation/guide_complete.rst @@ -130,7 +130,7 @@ Although it is possible to run AiiDA without a daemon it does provide significan .. important:: The ``aiida-core.services`` package ensures that RabbitMQ is installed in the conda environment. - However, it is not a _service_, in the sense that it is not automatically started, but has to be started manually. + However, it is not a *service*, in the sense that it is not automatically started, but has to be started manually. .. code-block:: console diff --git a/docs/source/installation/guide_quick.rst b/docs/source/installation/guide_quick.rst index af9aaa8dc0..25ef307d57 100644 --- a/docs/source/installation/guide_quick.rst +++ b/docs/source/installation/guide_quick.rst @@ -51,13 +51,31 @@ If none of the lines show a red cross, indicating a problem, the installation wa Quick install limitations ========================= +By default, ``verdi presto`` creates a profile that uses SQLite instead of PostgreSQL and does not use the RabbitMQ message broker. +The table below gives a quick overview of the functionality that is not supported in those cases: + ++-----------------------------------------+------------------------------------------------------------------------+ +| No RabbitMQ | SQLite instead of PostgreSQL | ++=========================================+========================================================================+ +| Cannot run the daemon | Not suitable for high-throughput workloads | ++-----------------------------------------+------------------------------------------------------------------------+ +| Cannot submit processes to the daemon\* | No support for ``has_key`` and ``contains`` operators in query builder | ++-----------------------------------------+------------------------------------------------------------------------+ +| Cannot play, pause, kill processes | No support for ``QueryBuilder.get_creation_statistics`` | ++-----------------------------------------+------------------------------------------------------------------------+ + +\* Calculations can still be run on remote computers + +.. note:: + To enable the RabbitMQ broker for an existing profile, :ref:`install RabbitMQ ` and then run ``verdi profile configure-rabbitmq``. + Functionality ------------- Part of AiiDA's functionality requires a `message broker `_, with the default implementation using `RabbitMQ `_. The message broker is used to allow communication with the :ref:`daemon `. Since RabbitMQ is a separate service and is not always trivial to install, the quick installation guide sets up a profile that does not require it. -As a result, the daemon cannot be started and processes cannot be submitted to it but can only be run locally. +As a result, the daemon cannot be started and processes cannot be submitted to it but can only be run in the current Python interpreter. .. note:: The ``verdi presto`` command automatically checks if RabbitMQ is running on the localhost. diff --git a/src/aiida/cmdline/commands/cmd_presto.py b/src/aiida/cmdline/commands/cmd_presto.py index 83ba287a94..09d7070e7c 100644 --- a/src/aiida/cmdline/commands/cmd_presto.py +++ b/src/aiida/cmdline/commands/cmd_presto.py @@ -178,7 +178,7 @@ def verdi_presto( created profile uses the new PostgreSQL database instead of SQLite. """ from aiida.brokers.rabbitmq.defaults import detect_rabbitmq_config - from aiida.common import exceptions + from aiida.common import docs, exceptions from aiida.manage.configuration import create_profile, load_profile from aiida.orm import Computer @@ -217,6 +217,7 @@ def verdi_presto( broker_config = detect_rabbitmq_config() except ConnectionError as exception: echo.echo_report(f'RabbitMQ server not found ({exception}): configuring the profile without a broker.') + echo.echo_report(f'See {docs.URL_NO_BROKER} for details on the limitations of running without a broker.') else: echo.echo_report('RabbitMQ server detected: configuring the profile with a broker.') broker_backend = 'core.rabbitmq' diff --git a/src/aiida/cmdline/commands/cmd_process.py b/src/aiida/cmdline/commands/cmd_process.py index 77e14a3300..c9c492ae14 100644 --- a/src/aiida/cmdline/commands/cmd_process.py +++ b/src/aiida/cmdline/commands/cmd_process.py @@ -101,6 +101,7 @@ def process_list( from aiida.cmdline.commands.cmd_daemon import execute_client_command from aiida.cmdline.utils.common import print_last_process_state_change + from aiida.common.docs import URL_NO_BROKER from aiida.common.exceptions import ConfigurationError from aiida.engine.daemon.client import get_daemon_client from aiida.orm import ProcessNode, QueryBuilder @@ -137,7 +138,7 @@ def process_list( try: client = get_daemon_client() except ConfigurationError: - echo.echo_warning('This profile does not have a broker and so it has no daemon.') + echo.echo_warning(f'This profile does not have a broker and so it has no daemon. See {URL_NO_BROKER}') return if not client.is_daemon_running: diff --git a/src/aiida/cmdline/commands/cmd_profile.py b/src/aiida/cmdline/commands/cmd_profile.py index 057f2de5a9..3dd21b56bf 100644 --- a/src/aiida/cmdline/commands/cmd_profile.py +++ b/src/aiida/cmdline/commands/cmd_profile.py @@ -55,6 +55,7 @@ def command_create_profile( :param kwargs: Arguments to initialise instance of the selected storage implementation. """ from aiida.brokers.rabbitmq.defaults import detect_rabbitmq_config + from aiida.common import docs from aiida.plugins.entry_point import get_entry_point_from_class if not storage_cls.read_only and email is None: @@ -79,6 +80,7 @@ def command_create_profile( else: echo.echo_report('Creating profile without RabbitMQ.') echo.echo_report('It can be configured at a later point in time with `verdi profile configure-rabbitmq`.') + echo.echo_report(f'See {docs.URL_NO_BROKER} for details on the limitations of running without a broker.') try: profile = create_profile( diff --git a/src/aiida/cmdline/commands/cmd_status.py b/src/aiida/cmdline/commands/cmd_status.py index dc4521af02..f3c32327dc 100644 --- a/src/aiida/cmdline/commands/cmd_status.py +++ b/src/aiida/cmdline/commands/cmd_status.py @@ -58,6 +58,7 @@ class ServiceStatus(enum.IntEnum): def verdi_status(print_traceback, no_rmq): """Print status of AiiDA services.""" from aiida import __version__ + from aiida.common.docs import URL_NO_BROKER from aiida.common.exceptions import ConfigurationError from aiida.engine.daemon.client import DaemonException, DaemonNotRunningException from aiida.manage.configuration.settings import AIIDA_CONFIG_FOLDER @@ -141,7 +142,7 @@ def verdi_status(print_traceback, no_rmq): print_status( ServiceStatus.WARNING, 'broker', - 'No broker defined for this profile: certain functionality not available.', + f'No broker defined for this profile: certain functionality not available. See {URL_NO_BROKER}', ) # Getting the daemon status @@ -151,7 +152,7 @@ def verdi_status(print_traceback, no_rmq): print_status( ServiceStatus.WARNING, 'daemon', - 'No broker defined for this profile: daemon is not available.', + 'No broker defined for this profile: daemon is not available. See {URL_NO_BROKER}', ) except DaemonNotRunningException as exception: print_status(ServiceStatus.WARNING, 'daemon', str(exception)) diff --git a/src/aiida/cmdline/utils/decorators.py b/src/aiida/cmdline/utils/decorators.py index 84386710f9..5363926978 100644 --- a/src/aiida/cmdline/utils/decorators.py +++ b/src/aiida/cmdline/utils/decorators.py @@ -45,6 +45,7 @@ def with_broker(wrapped, _, args, kwargs): If the currently loaded profile does not define a broker, the command is aborted. """ + from aiida.common.docs import URL_NO_BROKER from aiida.manage import get_manager broker = get_manager().get_broker() @@ -54,6 +55,7 @@ def with_broker(wrapped, _, args, kwargs): if broker is None: echo.echo_critical( f'Profile `{profile.name}` does not support this functionality as it does not provide a broker.' + f'See {URL_NO_BROKER} for more details.' ) kwargs['broker'] = broker @@ -313,6 +315,7 @@ def start_daemon(): If the loaded profile does not define a broker, the command will exit with a critical error. """ + from aiida.common.docs import URL_NO_BROKER from aiida.manage import get_manager manager = get_manager() @@ -323,6 +326,9 @@ def start_daemon(): assert profile is not None if manager.get_broker() is None: - echo.echo_critical(f'profile `{profile.name}` does not define a broker and so cannot use this functionality.') + echo.echo_critical( + f'profile `{profile.name}` does not define a broker and so cannot use this functionality.' + f'See {URL_NO_BROKER} for more details.' + ) return wrapped(*args, **kwargs) diff --git a/src/aiida/common/docs.py b/src/aiida/common/docs.py new file mode 100644 index 0000000000..797c944387 --- /dev/null +++ b/src/aiida/common/docs.py @@ -0,0 +1,4 @@ +"""Collection of links to the documentation that can be used in log messages for reference.""" + +URL_BASE = 'https://aiida-core.readthedocs.io/en/stable' +URL_NO_BROKER = f'{URL_BASE}/installation/guide_quick.html#quick-install-limitations' diff --git a/src/aiida/engine/daemon/client.py b/src/aiida/engine/daemon/client.py index 67ca7b99b5..ef250802f7 100644 --- a/src/aiida/engine/daemon/client.py +++ b/src/aiida/engine/daemon/client.py @@ -91,6 +91,8 @@ def __init__(self, profile: Profile): :param profile: The profile instance. """ + from aiida.common.docs import URL_NO_BROKER + type_check(profile, Profile) config = get_config() self._profile = profile @@ -99,7 +101,8 @@ def __init__(self, profile: Profile): if self._profile.process_control_backend is None: raise ConfigurationError( - f'profile `{self._profile.name}` does not define a broker so the daemon cannot be used.' + f'profile `{self._profile.name}` does not define a broker so the daemon cannot be used. ' + f'See {URL_NO_BROKER} for more details.' ) @property diff --git a/src/aiida/engine/launch.py b/src/aiida/engine/launch.py index d37cf46905..34fd1d7c0d 100644 --- a/src/aiida/engine/launch.py +++ b/src/aiida/engine/launch.py @@ -103,6 +103,8 @@ def submit( :param kwargs: inputs to be passed to the process. This is an alternative to the positional ``inputs`` argument. :return: the calculation node of the process """ + from aiida.common.docs import URL_NO_BROKER + inputs = prepare_inputs(inputs, **kwargs) # Submitting from within another process requires ``self.submit``` unless it is a work function, in which case the @@ -117,7 +119,8 @@ def submit( 'Cannot submit because the runner does not have a process controller, probably because the profile does ' 'not define a broker like RabbitMQ. If a RabbitMQ server is available, the profile can be configured to ' 'use it with `verdi profile configure-rabbitmq`. Otherwise, use :meth:`aiida.engine.launch.run` instead to ' - 'run the process in the local Python interpreter instead of submitting it to the daemon.' + 'run the process in the local Python interpreter instead of submitting it to the daemon. ' + f'See {URL_NO_BROKER} for more details.' ) assert runner.persister is not None, 'runner does not have a persister'