diff --git a/doc/changelog.d/5147.maintenance.md b/doc/changelog.d/5147.maintenance.md new file mode 100644 index 00000000000..835a23aea4f --- /dev/null +++ b/doc/changelog.d/5147.maintenance.md @@ -0,0 +1 @@ +Increase start_timeout and link it to Fluent's Idle timeout diff --git a/pyproject.toml b/pyproject.toml index 69a6ce79a60..38bf389a503 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ "Operating System :: OS Independent" ] dependencies = [ - "ansys-api-fluent>=0.3.40", + "ansys-api-fluent>=0.3.41", "ansys-platform-instancemanagement~=1.1", "ansys-tools-common>=0.4.0", "ansys-tools-filetransfer>=0.2,<1.0", diff --git a/src/ansys/fluent/core/launcher/container_launcher.py b/src/ansys/fluent/core/launcher/container_launcher.py index 2f5d37ab494..ffffa16c169 100644 --- a/src/ansys/fluent/core/launcher/container_launcher.py +++ b/src/ansys/fluent/core/launcher/container_launcher.py @@ -173,7 +173,7 @@ def __init__( Specifies the number of processors to use. Defaults to ``None``, which uses 1 processor. In job scheduler environments, this value limits the total number of allocated cores. start_timeout : int, optional - Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 60 seconds. + Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 180 seconds. additional_arguments : str, optional Additional command-line arguments for Fluent, formatted as they would be on the command line. container_dict : dict, optional @@ -238,7 +238,7 @@ def __init__( if "start_watchdog" not in self.argvals: self.argvals["start_watchdog"] = None if self.argvals.get("start_timeout") is None: - self.argvals["start_timeout"] = 60 + self.argvals["start_timeout"] = 180 self.file_transfer_service = kwargs.get("file_transfer_service") if self.argvals["mode"] == FluentMode.SOLVER_ICING: self.argvals["fluent_icing"] = True diff --git a/src/ansys/fluent/core/launcher/fluent_container.py b/src/ansys/fluent/core/launcher/fluent_container.py index 5149f48cc84..a5d4d5933ca 100644 --- a/src/ansys/fluent/core/launcher/fluent_container.py +++ b/src/ansys/fluent/core/launcher/fluent_container.py @@ -473,7 +473,7 @@ def configure_container_dict( def start_fluent_container( args: list[str], container_dict: dict | None = None, - start_timeout: int = 60, + start_timeout: int = 180, compose_config: ComposeConfig | None = None, ) -> tuple[int, str, Any]: """Start a Fluent container. @@ -485,7 +485,7 @@ def start_fluent_container( container_dict : dict, optional Dictionary with Docker container configuration. start_timeout : int, optional - Timeout in seconds for the container to start. If not specified, it defaults to 60 + Timeout in seconds for the container to start. If not specified, it defaults to 180 seconds. compose_config : ComposeConfig, optional Configuration for Docker Compose, if using Docker Compose to launch the container. diff --git a/src/ansys/fluent/core/launcher/standalone_launcher.py b/src/ansys/fluent/core/launcher/standalone_launcher.py index 339a7412aec..b4725cff10f 100644 --- a/src/ansys/fluent/core/launcher/standalone_launcher.py +++ b/src/ansys/fluent/core/launcher/standalone_launcher.py @@ -36,6 +36,7 @@ """ import logging +import math import os from pathlib import Path import subprocess @@ -166,7 +167,7 @@ def __init__( journal_file_names : str or list of str, optional Path(s) to a Fluent journal file(s) that Fluent will execute. Defaults to ``None``. start_timeout : int, optional - Maximum time in seconds allowed for connecting to the Fluent server. Defaults to 60 seconds. + Maximum time in seconds allowed for connecting to the Fluent server. Defaults to 180 seconds. additional_arguments : str, optional Additional command-line arguments for Fluent, formatted as they would be on the command line. env : dict[str, str], optional @@ -222,7 +223,16 @@ def __init__( kwargs["ui_mode"] = UIMode.GUI self.argvals["ui_mode"] = UIMode(kwargs.get("ui_mode")) if self.argvals.get("start_timeout") is None: - self.argvals["start_timeout"] = 60 + self.argvals["start_timeout"] = 180 + # +1 ensures the minute-granularity timer never fires before start_timeout elapses. + _idle_timeout_minutes = math.ceil(self.argvals["start_timeout"] / 60) + 1 + _set_timeout_arg = ( + f'-command="(set-session-idle-timeoutPLF+{_idle_timeout_minutes})"' + ) + if self.argvals["additional_arguments"]: + self.argvals["additional_arguments"] += f" {_set_timeout_arg}" + else: + self.argvals["additional_arguments"] = _set_timeout_arg if self.argvals.get("lightweight_mode") is None: self.argvals["lightweight_mode"] = False fluent_version = _get_standalone_launch_fluent_version(self.argvals) @@ -278,7 +288,7 @@ def __call__( try: _await_fluent_launch( self._server_info_file_name, - self.argvals.get("start_timeout", 60), + self.argvals.get("start_timeout", 180), self._sifile_last_mtime, process.pid, ) @@ -293,7 +303,7 @@ def __call__( process = subprocess.Popen(launch_cmd, **self._kwargs) _await_fluent_launch( self._server_info_file_name, - self.argvals.get("start_timeout", 60), + self.argvals.get("start_timeout", 180), self._sifile_last_mtime, process.pid, ) @@ -326,6 +336,18 @@ def __call__( ip, inside_container=False, ) + # PyFluent is now connected: disable the idle-timeout guard. + try: + if session.get_fluent_version() >= FluentVersion.v271: + session._app_utilities.set_idle_timeout( + session.preferences.General.IdleTimeout() * 60 + ) + else: + session.scheme_eval.eval( + f"(set-session-idle-timeout {session.preferences.General.IdleTimeout()})" + ) + except Exception as ex: + logger.debug(f"Could not reset Idle Timeout: {ex}") if self.argvals.get("case_file_name"): if FluentMode.is_meshing(self.argvals.get("mode")): session.tui.file.read_case(self.argvals.get("case_file_name")) diff --git a/src/ansys/fluent/core/module_config.py b/src/ansys/fluent/core/module_config.py index 27e47c6db87..02c9f6444e3 100644 --- a/src/ansys/fluent/core/module_config.py +++ b/src/ansys/fluent/core/module_config.py @@ -263,9 +263,9 @@ class Config: lambda instance: instance._env.get("PYFLUENT_USE_PODMAN_COMPOSE") == "1" ) - #: The timeout in seconds to wait for Fluent to launch, defaults to the value of ``PYFLUENT_FLUENT_LAUNCH_TIMEOUT`` environment variable or 60 seconds. + #: The timeout in seconds to wait for Fluent to launch, defaults to the value of ``PYFLUENT_FLUENT_LAUNCH_TIMEOUT`` environment variable or 180 seconds. launch_fluent_timeout = _ConfigDescriptor["Config"]( - lambda instance: int(instance._env.get("PYFLUENT_FLUENT_LAUNCH_TIMEOUT", 60)) + lambda instance: int(instance._env.get("PYFLUENT_FLUENT_LAUNCH_TIMEOUT", 180)) ) #: Whether to show the Fluent GUI when launching the server, defaults to the value of ``PYFLUENT_SHOW_SERVER_GUI`` environment variable. diff --git a/src/ansys/fluent/core/services/app_utilities_v1.py b/src/ansys/fluent/core/services/app_utilities_v1.py index cca05189349..445b479a61b 100644 --- a/src/ansys/fluent/core/services/app_utilities_v1.py +++ b/src/ansys/fluent/core/services/app_utilities_v1.py @@ -96,6 +96,12 @@ def cancel_pause_solve( """CancelPauseSolve RPC of Events service (v1).""" return self._events_stub.CancelPauseSolve(request, metadata=self._metadata) + def set_idle_timeout( + self, request: AppUtilitiesProtoModule.SetIdleTimeoutRequest + ) -> AppUtilitiesProtoModule.SetIdleTimeoutResponse: + """SetIdleTimeout RPC of ApplicationRuntime service (v1).""" + return self._stub.SetIdleTimeout(request, metadata=self._metadata) + class AppUtilities(_AppUtilitiesV0): """AppUtilities (v1 proto API).""" @@ -162,6 +168,18 @@ def is_solution_data_available(self) -> bool: response = self.service.is_data_available(request) return response.is_data_available + def set_idle_timeout(self, timeout: int) -> None: + """Set the Fluent session idle timeout. + + Parameters + ---------- + timeout : int + Idle timeout duration in seconds. Pass 0 to disable the idle timeout. + """ + request = AppUtilitiesProtoModule.SetIdleTimeoutRequest() + request.timeout.seconds = timeout + self.service.set_idle_timeout(request) + class AppUtilitiesV252(AppUtilities): """AppUtilitiesV252 (v1 proto API). diff --git a/src/ansys/fluent/core/session_utilities.py b/src/ansys/fluent/core/session_utilities.py index f82aae6f11b..de3100609a6 100644 --- a/src/ansys/fluent/core/session_utilities.py +++ b/src/ansys/fluent/core/session_utilities.py @@ -134,7 +134,7 @@ def from_install( # pylint: disable=missing-param-doc journal_file_names : str or list of str, optional Path(s) to a Fluent journal file(s) that Fluent will execute. Defaults to ``None``. start_timeout : int, optional - Maximum time in seconds allowed for connecting to the Fluent server. Defaults to 60 seconds. + Maximum time in seconds allowed for connecting to the Fluent server. Defaults to 180 seconds. additional_arguments : str, optional Additional command-line arguments for Fluent, formatted as they would be on the command line. env : dict[str, str], optional @@ -239,7 +239,7 @@ def from_container( # pylint: disable=missing-param-doc Specifies the number of processors to use. Defaults to ``None``, which uses 1 processor. In job scheduler environments, this value limits the total number of allocated cores. start_timeout : int, optional - Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 60 seconds. + Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 180 seconds. additional_arguments : str, optional Additional command-line arguments for Fluent, formatted as they would be on the command line. container_dict : dict, optional @@ -326,7 +326,7 @@ def from_pim( # pylint: disable=missing-param-doc Specifies the number of processors to use. Defaults to ``None``, which uses 1 processor. In job scheduler environments, this value limits the total number of allocated cores. start_timeout : int, optional - Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 60 seconds. + Maximum allowable time in seconds for connecting to the Fluent server. Defaults to 180 seconds. additional_arguments : str, optional Additional command-line arguments for Fluent, formatted as they would be on the command line. cleanup_on_exit : bool