feat(rpc-base): set default RPC timeout and allow customization

This commit is contained in:
2026-05-20 13:15:21 +02:00
committed by Jan Wyzula
parent 5e8f0e8083
commit f03a5d9e85
3 changed files with 29 additions and 3 deletions
+11
View File
@@ -222,6 +222,7 @@ class BECGuiClient(RPCBase):
self._ipython_registry: dict[str, RPCReference] = {}
self.available_widgets = AvailableWidgetsNamespace()
register_serializer_extension()
self._rpc_timeout = 5
####################
#### Client API ####
@@ -232,6 +233,16 @@ class BECGuiClient(RPCBase):
"""The launcher object."""
return RPCBase(gui_id=f"{self._gui_id}:launcher", parent=self, object_name="launcher")
def set_rpc_timeout(self, timeout: float):
"""Set the timeout for RPC calls to the GUI server.
Args:
timeout(float): The timeout in seconds.
"""
if not isinstance(timeout, (int, float)) or timeout < 0:
raise ValueError("Timeout must be a non-negative number.")
self._rpc_timeout = timeout
def _safe_register_stream(self, endpoint: EndpointInfo, cb: Callable, **kwargs):
"""Check if already registered for registration in idempotent functions."""
if not self._client.connector.any_stream_is_registered(endpoint, cb=cb):
+9 -3
View File
@@ -24,6 +24,8 @@ else:
# pylint: disable=protected-access
_DEFAULT_RPC_TIMEOUT = object()
def _name_arg(arg):
if isinstance(arg, DeviceBaseWithConfig):
@@ -154,6 +156,7 @@ class RPCReference:
class RPCBase:
def __init__(
self,
gui_id: str | None = None,
@@ -211,8 +214,8 @@ class RPCBase:
self,
method,
*args,
wait_for_rpc_response=True,
timeout=5,
wait_for_rpc_response: bool = True,
timeout: float | None | object = _DEFAULT_RPC_TIMEOUT,
gui_id: str | None = None,
**kwargs,
) -> Any:
@@ -223,13 +226,16 @@ class RPCBase:
method: The method to call.
args: The arguments to pass to the method.
wait_for_rpc_response: Whether to wait for the RPC response.
timeout: The timeout for the RPC response.
timeout: The timeout for the RPC response. If omitted, the client's default RPC
timeout is used. If explicitly set to None, wait indefinitely.
gui_id: The GUI ID to use for the RPC call. If None, the default GUI ID is used.
kwargs: The keyword arguments to pass to the method.
Returns:
The result of the RPC call.
"""
if timeout is _DEFAULT_RPC_TIMEOUT:
timeout = self._root._rpc_timeout
if method in ["show", "hide", "raise"] and gui_id is None:
obj = self._root._server_registry.get(self._gui_id)
if obj is None:
+9
View File
@@ -5,6 +5,7 @@ import pytest
from bec_widgets.cli.client import BECDockArea
from bec_widgets.cli.client_utils import BECGuiClient, _start_plot_process
from bec_widgets.cli.rpc.rpc_base import RPCBase, RPCResponseTimeoutError, rpc_timeout
@pytest.fixture
@@ -257,3 +258,11 @@ def test_client_utils_delete_falls_back_to_direct_close():
gui.delete("dock")
widget._run_rpc.assert_called_once_with("close")
def test_client_utils_gui_client_set_rpc_timeout():
gui = BECGuiClient()
assert gui._rpc_timeout == 5
gui.set_rpc_timeout(10)
assert gui._rpc_timeout == 10