plesty.server.services.agent ============================ .. py:module:: plesty.server.services.agent .. autoapi-nested-parse:: The bench agent: runs ``plesty-server`` commands for a remote :mod:`plesty.bench` client. A ZMQ ROUTER on the agent port (5550) speaking the plesty-lib device-server wire. Three request types — ``describe``, ``exec``, ``fetch`` — documented in :mod:`plesty.bench.client`. ``exec`` runs the click application **in-process** with its output captured, with the agent's own ``--home``/ ``-f`` prepended, so every command the CLI has is remote with nothing to keep in sync. Each request is handled on a worker thread (a ``start`` waits for its probe; a ``describe`` must not wait behind it); replies go back through the socket thread, since a ZMQ socket belongs to one thread. Trust model: the bench network, like the device servers — a shared token (``--token`` / ``PLESTY_BENCH_TOKEN``) checked on every ``exec``/``fetch``, ``fetch`` confined to the bench home, no ``agent``/``gui`` through ``exec``. Attributes ---------- .. autoapisummary:: plesty.server.services.agent.DEFAULT_BIND plesty.server.services.agent.TOKEN_ENV plesty.server.services.agent.FORBIDDEN plesty.server.services.agent.FETCH_LIMIT Classes ------- .. autoapisummary:: plesty.server.services.agent.Agent Functions --------- .. autoapisummary:: plesty.server.services.agent.serve_in_thread plesty.server.services.agent._ok plesty.server.services.agent._error plesty.server.services.agent._frame plesty.server.services.agent._version Module Contents --------------- .. py:data:: DEFAULT_BIND :value: 'tcp://*:5550' .. py:data:: TOKEN_ENV :value: 'PLESTY_BENCH_TOKEN' .. py:data:: FORBIDDEN .. py:data:: FETCH_LIMIT :value: 16777216 .. py:class:: Agent(home: plesty.server.model.home.Home, fleet_path: str | os.PathLike[str] | None = None, bind: str = DEFAULT_BIND, token: str | None = None, workers: int = 4) Serve ``plesty.bench`` clients for one bench. Configure the agent. :param home: The bench home every command runs against. :param fleet_path: Fleet file passed to every command (``-f``), or ``None``. :param bind: ZMQ endpoint to bind. :param token: Shared secret; ``None`` reads ``PLESTY_BENCH_TOKEN``; empty means no check (a bench on a trusted network). :param workers: Concurrent requests. .. py:attribute:: home .. py:attribute:: fleet_path .. py:attribute:: bind :value: 'tcp://*:5550' .. py:attribute:: token .. py:attribute:: workers :value: 4 .. py:attribute:: bound :type: str | None :value: None .. py:attribute:: served :value: 0 .. py:method:: handle(message: Any) -> dict[str, Any] Answer one decoded request (pure; no socket involved). .. py:method:: description() -> dict[str, Any] What ``describe`` returns. .. py:method:: exec(argv: collections.abc.Sequence[Any]) -> dict[str, Any] Run ``plesty-server `` in-process against this bench; capture everything. .. py:method:: fetch(path: str) -> dict[str, Any] Read a file under the bench home; *path* is relative to it. .. py:method:: serve(stop: threading.Event, poll_ms: int = 100, max_replies: int | None = None) -> int Bind and answer requests until *stop* is set; returns the number answered. :param stop: Set to end the loop. :param poll_ms: Socket poll interval. :param max_replies: Stop once this many replies went out (tests). .. py:function:: serve_in_thread(agent: Agent, stop: threading.Event | None = None) -> tuple[threading.Thread, threading.Event] Run *agent* on a daemon thread; returns the thread and its stop event. .. py:function:: _ok(result: Any) -> dict[str, Any] .. py:function:: _error(message: str, kind: str) -> dict[str, Any] .. py:function:: _frame(reply: dict[str, Any]) -> bytes .. py:function:: _version() -> str