rskit_provider/traits.rs
1use std::future::Future;
2use std::pin::Pin;
3
4use futures::Stream as FuturesStream;
5use rskit_errors::AppResult;
6
7/// Boxed stream of `AppResult<O>`.
8pub type BoxStream<O> = Pin<Box<dyn FuturesStream<Item = AppResult<O>> + Send + 'static>>;
9
10// ─── Base ─────────────────────────────────────────────────────────────────────
11
12/// Stable identity for a provider.
13#[async_trait::async_trait]
14pub trait Provider: Send + Sync {
15 /// Stable name identifying this provider instance (used in logs and spans).
16 fn name(&self) -> &'static str;
17}
18
19// ─── Interaction patterns ─────────────────────────────────────────────────────
20
21/// Unary request → single response (HTTP POST, gRPC unary, DB query).
22///
23/// # Example
24///
25/// ```rust
26/// use rskit_errors::AppResult;
27/// use rskit_provider::{Provider, RequestResponse};
28///
29/// struct Echo;
30///
31/// impl Provider for Echo {
32/// fn name(&self) -> &'static str {
33/// "echo"
34/// }
35/// }
36///
37/// #[async_trait::async_trait]
38/// impl RequestResponse<String, String> for Echo {
39/// async fn execute(&self, input: String) -> AppResult<String> {
40/// Ok(input.to_uppercase())
41/// }
42/// }
43///
44/// # #[tokio::main]
45/// # async fn main() -> AppResult<()> {
46/// let response = Echo.execute("hello".to_string()).await?;
47/// assert_eq!(response, "HELLO");
48/// # Ok(())
49/// # }
50/// ```
51#[async_trait::async_trait]
52pub trait RequestResponse<I, O>: Provider
53where
54 I: Send + 'static,
55 O: Send + 'static,
56{
57 /// Execute the request and return a single response.
58 async fn execute(&self, input: I) -> AppResult<O>;
59}
60
61/// One input → bounded or backpressure-aware stream of outputs (gRPC server-stream, SSE, live query).
62///
63/// Implementations must document their buffering and backpressure behavior.
64pub trait Stream<I, O>: Provider
65where
66 I: Send + 'static,
67 O: Send + 'static,
68{
69 /// Execute the request and return a stream of responses.
70 fn execute(&self, input: I) -> impl Future<Output = AppResult<BoxStream<O>>> + Send + '_;
71}
72
73/// Write-only (Kafka publish, webhook, S3 put, log sink).
74///
75/// Implementations must apply downstream backpressure or return a typed error
76/// instead of buffering without a bound.
77pub trait Sink<I>: Provider
78where
79 I: Send + 'static,
80{
81 /// Send a single item downstream.
82 fn send(&self, input: I) -> impl Future<Output = AppResult<()>> + Send + '_;
83}
84
85/// Bidirectional channel (WebSocket, gRPC bidi-stream).
86///
87/// Implementations must document channel buffering and close semantics.
88pub trait Duplex<I, O>: Provider
89where
90 I: Send + 'static,
91 O: Send + 'static,
92{
93 /// Open a new bidirectional channel.
94 fn open(&self) -> impl Future<Output = AppResult<Box<dyn DuplexChannel<I, O>>>> + Send + '_;
95}
96
97/// Handle to an open bidirectional channel.
98#[async_trait::async_trait]
99pub trait DuplexChannel<I, O>: Send
100where
101 I: Send + 'static,
102 O: Send + 'static,
103{
104 /// Send a message to the remote end.
105 async fn send(&mut self, input: I) -> AppResult<()>;
106 /// Receive the next message from the remote end; `None` means the channel is closed.
107 async fn recv(&mut self) -> AppResult<Option<O>>;
108 /// Close the channel gracefully.
109 async fn close(&mut self) -> AppResult<()>;
110}