Skip to main content

dnet_rpc/
lib.rs

1#![warn(missing_docs)]
2
3//! RPC over `dnet` transports.
4
5pub mod consumer;
6pub use consumer::{Consume, StreamRequest, ValueRequest};
7
8pub mod producer;
9
10pub mod parts;
11
12use std::fmt::{Debug, Display};
13use std::future::Future;
14
15use dportable::create_non_sync_send_variant_for_wasm;
16
17pub use dportable::time::{sleep, Instant, Sleep, Timeout};
18pub use dportable::{spawn, JoinHandle};
19
20pub use dnet_base;
21
22pub use atomic_counter;
23pub use futures;
24
25/// Macro for marking traits defining api's interface.
26///
27/// It will generate the following:
28/// - `Consumer` struct implementing [Consume] trait - which can be used to make requests,
29/// - `Request` enum - serializable structure representing request type with its arguments,
30/// - `Response` enum - serializable structure representing response to a request,
31/// - `impl_produce` macro which is used by [Produce] derive macro to implement
32///   [producer::Produce] trait.
33///
34/// [Consume]: self::Consume
35pub use dnet_macros::api;
36
37/// Used together with [api] macro, disables attachment of [serde] `Serialize` and/or
38/// `Deserialize` derive macros on generated `Request` and/or `Response` enums.
39///
40/// Following options are available:
41/// - `request` - disables both `Serialize` and `Deserialize` for generated `Request` enum,
42/// - `response` - disables both `Serialize` and `Deserialize` for generated `Response` enum,
43/// - `request_serialize` - disables `Serialize` for generated `Request` enum,
44/// - `request_deserialize` - disables `Deserialize` for generated `Request` enum,
45/// - `response_serialize` - disables `Serialize` for generated `Response` enum,
46/// - `response_deserialize` - disables `Deserialize` for generated `Response` enum.
47///
48/// Use without arguments - `#[no_serde]` - is equivalent to `#[no_serde(request, response)]`.
49pub use dnet_macros::no_serde;
50
51/// Marker for api functions that are "fire-and-forget" - they return as soon as request is
52/// sent to the producer without waiting for response - in fact producer won't even send it.
53///
54/// It is useful for cases of one-directional communication where you don't care about
55/// the producer finishing the task.
56pub use dnet_macros::no_ack;
57
58/// Marker for api functions that will provide producer with
59/// [AbortionToken](crate::producer::abortable::AbortionToken)
60/// which will be triggered when consumer aborts the request.
61///
62/// Abortion will be passed as the last argument of the producer method as
63/// `abortion_token: AbortionToken`.
64pub use dnet_macros::abortable;
65
66/// Derive macro implementing [Produce] trait for struct.
67///
68/// **NOTE**: it depends on `impl_produce` macro, `Request` and `Response` enums
69/// generated by the [api] macro being in scope.
70///
71/// [Produce]: self::producer::Produce
72pub use dnet_macros::Produce;
73
74create_non_sync_send_variant_for_wasm! {
75    /// Helper trait for consumer errors.
76    pub trait TransportError: Send + 'static {}
77
78    impl<T> TransportError for T where T: Send + 'static {}
79}
80
81create_non_sync_send_variant_for_wasm! {
82    /// Helper trait for transports used by `dnet-rpc`.
83    pub trait Transport<Incoming, Outgoing, Error>:
84        dnet_base::Transport<Incoming, Outgoing, Error> + Send + 'static
85    {
86    }
87
88    impl<T, Incoming, Outgoing, Error> Transport<Incoming, Outgoing, Error> for T where
89        T: dnet_base::Transport<Incoming, Outgoing, Error> + Send + 'static
90    {
91    }
92}
93
94create_non_sync_send_variant_for_wasm! {
95    /// Helper trait for shutdown futures used by producers and consumers.
96    pub trait Shutdown: Future<Output = ShutdownType> + Send + Unpin + 'static {}
97
98    impl<T> Shutdown for T where T: Future<Output = ShutdownType> + Send + Unpin + 'static {}
99}
100
101/// RPC error.
102#[derive(Debug)]
103pub enum Error {
104    /// Connection closed.
105    Closed,
106
107    /// Request was aborted by consumer/producer.
108    Aborted,
109
110    /// Consumer/producer was shut down.
111    ///
112    /// **NOTE**: It may also be caused by connection being closed before consumer
113    /// request was made.
114    Shutdown,
115
116    /// Consumer timed out.
117    Timeout,
118
119    /// Consumer was dropped before request could complete.
120    Dropped,
121}
122
123impl Display for Error {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        match self {
126            Error::Closed => write!(f, "transport closed"),
127            Error::Aborted => write!(f, "request was aborted"),
128            Error::Shutdown => write!(f, "producer/consumer was shutdown"),
129            Error::Timeout => write!(f, "producer/consumer timed out"),
130            Error::Dropped => write!(f, "consumer was dropped"),
131        }
132    }
133}
134
135impl std::error::Error for Error {}
136
137/// Cause of producer/consumer shutdown.
138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139pub enum ShutdownType {
140    /// Connection closed.
141    Closed,
142
143    /// Manual shutdown.
144    Shutdown,
145
146    /// Abort all requests.
147    Aborted,
148
149    /// Consumer/producer timed out.
150    ///
151    /// **NOTE**: Consumer requests will not receive [Error::Timeout] error
152    /// (they will error out with other error type like [Error::Closed] or [Error::Shutdown]).
153    /// This design is deliberate to not give consumers easily determinable info about timeout
154    /// duration producer was configured with.
155    Timeout,
156}
157
158impl From<ShutdownType> for Error {
159    fn from(value: ShutdownType) -> Self {
160        match value {
161            ShutdownType::Closed => Error::Closed,
162            ShutdownType::Shutdown => Error::Shutdown,
163            ShutdownType::Aborted => Error::Aborted,
164            ShutdownType::Timeout => Error::Timeout,
165        }
166    }
167}