Add idiomatic documentation to Go, Java, Python, and Rust clients
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
//! High-level wrapper around the generated `MxAccessGateway` gRPC client.
|
||||
//!
|
||||
//! [`GatewayClient::connect`] builds an authenticated `tonic` channel using
|
||||
//! the supplied [`ClientOptions`], applies the bearer-token interceptor, and
|
||||
//! exposes typed methods for the unary and streaming RPCs. Most application
|
||||
//! code should prefer [`GatewayClient::open_session`] and the [`Session`]
|
||||
//! handle it returns, rather than the `*_raw` methods.
|
||||
|
||||
use std::fs;
|
||||
|
||||
use tonic::codegen::InterceptedService;
|
||||
@@ -14,11 +22,21 @@ use crate::generated::mxaccess_gateway::v1::{
|
||||
use crate::options::ClientOptions;
|
||||
use crate::session::Session;
|
||||
|
||||
/// Generated gateway client wrapped in the auth interceptor that
|
||||
/// [`GatewayClient`] uses internally.
|
||||
pub type RawGatewayClient = MxAccessGatewayClient<InterceptedService<Channel, AuthInterceptor>>;
|
||||
|
||||
/// Pinned, boxed [`MxEvent`] stream returned by
|
||||
/// [`GatewayClient::stream_events`]. Errors are pre-mapped from
|
||||
/// `tonic::Status` to [`Error`]; dropping the stream cancels the call.
|
||||
pub type EventStream =
|
||||
std::pin::Pin<Box<dyn futures_core::Stream<Item = Result<MxEvent, Error>> + Send + 'static>>;
|
||||
|
||||
/// Thin owner for the generated gateway client.
|
||||
/// Thin async wrapper around the generated gateway client.
|
||||
///
|
||||
/// The wrapper is `Clone`: every clone shares the underlying tonic channel
|
||||
/// (cheap, reference-counted) and the same call/stream timeouts. It is
|
||||
/// designed to be cheap enough to clone per request handler.
|
||||
#[derive(Clone)]
|
||||
pub struct GatewayClient {
|
||||
inner: RawGatewayClient,
|
||||
@@ -27,6 +45,13 @@ pub struct GatewayClient {
|
||||
}
|
||||
|
||||
impl GatewayClient {
|
||||
/// Connect to the gateway endpoint described by `options` and return a
|
||||
/// ready-to-use client.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`Error::InvalidEndpoint`] if the endpoint URL or CA file is
|
||||
/// malformed, and [`Error::Transport`] if the TCP/TLS handshake fails.
|
||||
pub async fn connect(options: ClientOptions) -> Result<Self, Error> {
|
||||
let mut endpoint =
|
||||
Channel::from_shared(options.endpoint().to_owned()).map_err(|source| {
|
||||
@@ -62,18 +87,30 @@ impl GatewayClient {
|
||||
})
|
||||
}
|
||||
|
||||
/// Borrow the underlying generated client. Use this only when you need
|
||||
/// access to RPCs not surfaced by the wrapper.
|
||||
pub fn raw_client(&mut self) -> &mut RawGatewayClient {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Consume the wrapper and return the underlying generated client.
|
||||
pub fn into_inner(self) -> RawGatewayClient {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Build a [`Session`] handle from a previously opened session id. No
|
||||
/// RPC is performed — this is the cheap counterpart to
|
||||
/// [`GatewayClient::open_session`] for callers that already own the id.
|
||||
pub fn session(&self, session_id: impl Into<String>) -> Session {
|
||||
Session::new(session_id, self.clone())
|
||||
}
|
||||
|
||||
/// Issue an `OpenSession` RPC and return the raw reply without
|
||||
/// validating its `protocol_status`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns the `tonic::Status` mapped through [`Error::from`].
|
||||
pub async fn open_session_raw(
|
||||
&self,
|
||||
request: OpenSessionRequest,
|
||||
@@ -83,12 +120,25 @@ impl GatewayClient {
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
/// Open a session, validate its `protocol_status`, and return a typed
|
||||
/// [`Session`] handle bound to this client.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`Error::ProtocolStatus`] if the gateway accepts the call
|
||||
/// but reports a non-OK protocol status, plus any of the
|
||||
/// [`Error`] variants produced by [`open_session_raw`](Self::open_session_raw).
|
||||
pub async fn open_session(&self, request: OpenSessionRequest) -> Result<Session, Error> {
|
||||
let reply = self.open_session_raw(request).await?;
|
||||
ensure_protocol_success("open session", reply.protocol_status.as_ref())?;
|
||||
Ok(Session::new(reply.session_id, self.clone()))
|
||||
}
|
||||
|
||||
/// Issue a `CloseSession` RPC and return the raw reply.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns the `tonic::Status` mapped through [`Error::from`].
|
||||
pub async fn close_session_raw(
|
||||
&self,
|
||||
request: CloseSessionRequest,
|
||||
@@ -98,16 +148,39 @@ impl GatewayClient {
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
/// Issue an `Invoke` RPC and return the raw reply, even when the
|
||||
/// command-level protocol status is non-OK.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns the `tonic::Status` mapped through [`Error::from`].
|
||||
pub async fn invoke_raw(&self, request: MxCommandRequest) -> Result<MxCommandReply, Error> {
|
||||
let mut client = self.inner.clone();
|
||||
let response = client.invoke(self.unary_request(request)).await?;
|
||||
Ok(response.into_inner())
|
||||
}
|
||||
|
||||
/// Issue an `Invoke` RPC and surface a non-OK reply as
|
||||
/// [`Error::Command`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`Error::Command`] when the reply's `protocol_status` is not
|
||||
/// `Ok`, plus any errors propagated by
|
||||
/// [`invoke_raw`](Self::invoke_raw).
|
||||
pub async fn invoke(&self, request: MxCommandRequest) -> Result<MxCommandReply, Error> {
|
||||
ensure_command_success(self.invoke_raw(request).await?)
|
||||
}
|
||||
|
||||
/// Open the server-streaming `StreamEvents` RPC.
|
||||
///
|
||||
/// The returned [`EventStream`] yields `MxEvent` messages as the worker
|
||||
/// produces them. Dropping the stream cancels the gRPC call cooperatively.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns the `tonic::Status` mapped through [`Error::from`] if the
|
||||
/// server rejects the subscription.
|
||||
pub async fn stream_events(&self, request: StreamEventsRequest) -> Result<EventStream, Error> {
|
||||
let mut client = self.inner.clone();
|
||||
let response = client.stream_events(self.stream_request(request)).await?;
|
||||
|
||||
Reference in New Issue
Block a user