Skip to main content

ServiceClientTrait

Trait ServiceClientTrait 

Source
pub trait ServiceClientTrait {
    type Error;

    // Required methods
    fn send_request_raw(&mut self, request: &[u8]) -> Result<(), Self::Error>;
    fn try_recv_reply_raw(
        &mut self,
        reply_buf: &mut [u8],
    ) -> Result<Option<usize>, Self::Error>;

    // Provided methods
    fn call_raw(
        &mut self,
        request: &[u8],
        _reply_buf: &mut [u8],
    ) -> Result<usize, Self::Error>
       where Self::Error: From<TransportError> { ... }
    fn send_request<S: RosService>(
        &mut self,
        request: &S::Request,
        req_buf: &mut [u8],
    ) -> Result<(), Self::Error>
       where Self::Error: From<TransportError> { ... }
    fn try_recv_reply<S: RosService>(
        &mut self,
        reply_buf: &mut [u8],
    ) -> Result<Option<S::Reply>, Self::Error>
       where Self::Error: From<TransportError> { ... }
    fn register_waker(&self, _waker: &Waker) { ... }
    fn start_server_discovery(
        &mut self,
        _timeout_ms: u32,
    ) -> Result<(), Self::Error> { ... }
    fn poll_server_discovery(&mut self) -> Result<Option<bool>, Self::Error> { ... }
    fn is_server_ready(&self) -> bool { ... }
    fn server_available(&self) -> Result<bool, Self::Error>
       where Self::Error: From<TransportError> { ... }
    fn call<S: RosService>(
        &mut self,
        request: &S::Request,
        req_buf: &mut [u8],
        _reply_buf: &mut [u8],
    ) -> Result<S::Reply, Self::Error>
       where Self::Error: From<TransportError> { ... }
}
Expand description

Service client trait for sending requests.

§Threading

&mut self on every method — the client is single-owner. For fan-out request patterns, create one client per worker thread.

§Calling pattern

All in-tree backends route blocking waits through the executor:

  1. send_request_raw(buf) — non-blocking; returns once the request is queued for transmission.
  2. The executor’s drive_io runs.
  3. try_recv_reply_raw(buf) — non-blocking; returns Ok(Some(len)) when the reply is back.

The deprecated call_raw blocking path is kept for backwards compatibility but should not be called.

Required Associated Types§

Source

type Error

Error type for service operations

Required Methods§

Source

fn send_request_raw(&mut self, request: &[u8]) -> Result<(), Self::Error>

Send a service request without waiting for a reply (non-blocking).

The caller must subsequently poll try_recv_reply_raw to retrieve the reply.

Source

fn try_recv_reply_raw( &mut self, reply_buf: &mut [u8], ) -> Result<Option<usize>, Self::Error>

Poll for a reply to the most recently sent request (non-blocking).

Returns Ok(Some(len)) when a reply has arrived, Ok(None) if not yet available, or Err on failure.

Provided Methods§

Source

fn call_raw( &mut self, request: &[u8], _reply_buf: &mut [u8], ) -> Result<usize, Self::Error>
where Self::Error: From<TransportError>,

👎Deprecated:

use Client::call → Promise::wait with an executor instead

Send a service request and wait for reply (blocking).

Deprecated — do not call. The default body returns Timeout immediately without polling. Use Client::callPromise::wait(executor, timeout_ms) which lets the executor drive I/O while waiting instead of busy-looping on try_recv_reply_raw with no sleep (which starves the transport on FreeRTOS / Zephyr single-threaded schedulers).

Backends that still need an internal blocking path should override this with a real sleep-between-polls implementation, but all in-tree backends (zenoh, XRCE) route blocking waits through the executor.

Source

fn send_request<S: RosService>( &mut self, request: &S::Request, req_buf: &mut [u8], ) -> Result<(), Self::Error>
where Self::Error: From<TransportError>,

Send a typed service request without waiting for a reply (non-blocking).

Serializes the request into req_buf and calls send_request_raw.

Source

fn try_recv_reply<S: RosService>( &mut self, reply_buf: &mut [u8], ) -> Result<Option<S::Reply>, Self::Error>
where Self::Error: From<TransportError>,

Poll for a typed reply to the most recently sent request (non-blocking).

Calls try_recv_reply_raw and deserializes if available.

Source

fn register_waker(&self, _waker: &Waker)

Register an async waker to be notified when a reply arrives.

Called from Future::poll() implementations to store the waker. The transport backend calls waker.wake() from its reply callback when a response is available, enabling event-driven async without busy-polling.

Default: no-op (backends that don’t support waking simply ignore this).

Source

fn start_server_discovery( &mut self, _timeout_ms: u32, ) -> Result<(), Self::Error>

Begin a server-discovery query on this client (non-blocking).

Models rclcpp::ClientBase::wait_for_service machinery: the backend fires off a discovery probe (typically a Zenoh liveliness query against the matching server’s wildcarded liveliness keyexpr) and the caller polls poll_server_discovery to collect the result.

Default impl: no-op success. Backends without a discovery channel (or those that always assume the server is reachable) can leave this default and have poll_server_discovery return Ok(Some(true)) immediately.

Source

fn poll_server_discovery(&mut self) -> Result<Option<bool>, Self::Error>

Poll an in-flight server-discovery query.

  • Ok(Some(true)) — at least one matching server has reported back; safe to send the first request.
  • Ok(Some(false)) — discovery query finished without finding any matching server (timeout / no-replies).
  • Ok(None) — query still in flight.
  • Err(_) — transport-level failure unrelated to server presence.

Default impl: returns Ok(Some(true)) (i.e., “server is always assumed reachable”). The Zenoh backend overrides this with a liveliness-token check.

Source

fn is_server_ready(&self) -> bool

Synchronous, non-blocking check of whether a matching server is currently visible.

Mirrors rclcpp::ClientBase::service_is_ready. Backends that lack discovery should keep the default true so existing call sites don’t regress.

Default impl: always true.

Source

fn server_available(&self) -> Result<bool, Self::Error>
where Self::Error: From<TransportError>,

Phase 124.C.1 — graph-aware server-availability probe.

Returns Ok(true) if at least one matching server has been discovered, Ok(false) if none yet, or Err(_) if the backend cannot answer (e.g. XRCE — micro-XRCE-DDS-Client has no participant enumeration). Distinct from is_server_ready, which collapses “don’t know” and “no server” into the same false answer.

User-facing surface: Client<S>::server_available() in Rust, nros_client_server_available() in C/C++. Clients use this to gate the first call_raw so a startup-ordering race (client opens before server’s discovery announcement lands) doesn’t surface as a request-side timeout.

Default impl: Err(TransportError::Unsupported) — backends that support graph introspection (zenoh queryable interest, DDS built-in topic readers) opt in by overriding.

Source

fn call<S: RosService>( &mut self, request: &S::Request, req_buf: &mut [u8], _reply_buf: &mut [u8], ) -> Result<S::Reply, Self::Error>
where Self::Error: From<TransportError>,

👎Deprecated:

use Client::call → Promise::wait with an executor instead

Call a service with typed messages (blocking).

Deprecated — do not call. The default body returns Timeout immediately without polling. Use Client::call on the executor instead, which drives I/O while waiting. See call_raw for the same reasoning.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§