1use bytes::Bytes;
6use std::collections::HashMap;
7use std::sync::atomic::{AtomicU64, Ordering};
8use std::sync::Arc;
9use tokio::sync::{mpsc, oneshot, Mutex, RwLock};
10
11use super::connection::{MultiplexError, MultiplexedConnection};
12
13pub struct PipelinedRequest {
15 pub id: u64,
17 pub stream_id: u16,
19 pub data: Bytes,
21 pub response_tx: oneshot::Sender<Result<Bytes, MultiplexError>>,
23}
24
25pub struct PipelinedClient {
27 connection: Arc<MultiplexedConnection>,
29 request_id: AtomicU64,
31 pending: Arc<RwLock<HashMap<u64, PendingRequest>>>,
33 max_in_flight: usize,
35 in_flight: Arc<std::sync::atomic::AtomicUsize>,
37}
38
39struct PendingRequest {
41 stream_id: u16,
42 response_tx: oneshot::Sender<Result<Bytes, MultiplexError>>,
43}
44
45impl PipelinedClient {
46 pub fn new(connection: Arc<MultiplexedConnection>, max_in_flight: usize) -> Self {
48 Self {
49 connection,
50 request_id: AtomicU64::new(1),
51 pending: Arc::new(RwLock::new(HashMap::new())),
52 max_in_flight,
53 in_flight: Arc::new(std::sync::atomic::AtomicUsize::new(0)),
54 }
55 }
56
57 pub fn connection(&self) -> &Arc<MultiplexedConnection> {
59 &self.connection
60 }
61
62 pub fn in_flight_count(&self) -> usize {
64 self.in_flight.load(Ordering::Relaxed)
65 }
66
67 pub fn can_send(&self) -> bool {
69 self.in_flight_count() < self.max_in_flight
70 }
71
72 pub async fn send(
75 &self,
76 data: Bytes,
77 ) -> Result<oneshot::Receiver<Result<Bytes, MultiplexError>>, MultiplexError> {
78 if !self.can_send() {
80 return Err(MultiplexError::SendBufferFull);
81 }
82
83 let stream_id = self.connection.open_stream().await?;
85
86 let request_id = self.request_id.fetch_add(1, Ordering::SeqCst);
88
89 let (response_tx, response_rx) = oneshot::channel();
91
92 {
94 let mut pending = self.pending.write().await;
95 pending.insert(
96 request_id,
97 PendingRequest {
98 stream_id,
99 response_tx,
100 },
101 );
102 }
103
104 self.in_flight.fetch_add(1, Ordering::AcqRel);
106
107 if let Err(error) = self.connection.send(stream_id, data).await {
109 self.pending.write().await.remove(&request_id);
110 self.in_flight.fetch_sub(1, Ordering::AcqRel);
111 self.connection.rollback_stream_open(stream_id).await;
112 return Err(error);
113 }
114
115 Ok(response_rx)
116 }
117
118 pub async fn send_batch(
120 &self,
121 requests: Vec<Bytes>,
122 ) -> Result<Vec<oneshot::Receiver<Result<Bytes, MultiplexError>>>, MultiplexError> {
123 let mut receivers = Vec::with_capacity(requests.len());
124
125 for data in requests {
126 let rx = self.send(data).await?;
127 receivers.push(rx);
128 }
129
130 Ok(receivers)
131 }
132
133 pub async fn process_response(
135 &self,
136 stream_id: u16,
137 data: Bytes,
138 ) -> Result<(), MultiplexError> {
139 let pending_request = {
141 let mut pending = self.pending.write().await;
142 let mut found_id = None;
143 for (id, req) in pending.iter() {
144 if req.stream_id == stream_id {
145 found_id = Some(*id);
146 break;
147 }
148 }
149 found_id.and_then(|id| pending.remove(&id))
150 };
151
152 if let Some(req) = pending_request {
153 self.in_flight.fetch_sub(1, Ordering::AcqRel);
155
156 let _ = req.response_tx.send(Ok(data));
158
159 self.connection.close_stream(stream_id).await?;
161 }
162
163 Ok(())
164 }
165
166 pub async fn process_error(
168 &self,
169 stream_id: u16,
170 error: MultiplexError,
171 ) -> Result<(), MultiplexError> {
172 let pending_request = {
174 let mut pending = self.pending.write().await;
175 let mut found_id = None;
176 for (id, req) in pending.iter() {
177 if req.stream_id == stream_id {
178 found_id = Some(*id);
179 break;
180 }
181 }
182 found_id.and_then(|id| pending.remove(&id))
183 };
184
185 if let Some(req) = pending_request {
186 self.in_flight.fetch_sub(1, Ordering::AcqRel);
188
189 let _ = req.response_tx.send(Err(error));
191 }
192
193 Ok(())
194 }
195
196 pub async fn cancel_all(&self) {
198 let mut pending = self.pending.write().await;
199 for (_, req) in pending.drain() {
200 let _ = req.response_tx.send(Err(MultiplexError::ConnectionClosed));
201 }
202 self.in_flight.store(0, Ordering::Release);
203 }
204
205 pub async fn pending_count(&self) -> usize {
207 self.pending.read().await.len()
208 }
209}
210
211pub struct RequestPipeline {
213 client: Arc<PipelinedClient>,
215 request_tx: mpsc::Sender<PipelinedRequest>,
217 request_rx: Mutex<mpsc::Receiver<PipelinedRequest>>,
219}
220
221impl RequestPipeline {
222 pub fn new(
224 connection: Arc<MultiplexedConnection>,
225 max_in_flight: usize,
226 buffer_size: usize,
227 ) -> Self {
228 let (request_tx, request_rx) = mpsc::channel(buffer_size);
229 let client = Arc::new(PipelinedClient::new(connection, max_in_flight));
230
231 Self {
232 client,
233 request_tx,
234 request_rx: Mutex::new(request_rx),
235 }
236 }
237
238 pub fn client(&self) -> &Arc<PipelinedClient> {
240 &self.client
241 }
242
243 pub async fn submit(
245 &self,
246 data: Bytes,
247 ) -> Result<oneshot::Receiver<Result<Bytes, MultiplexError>>, MultiplexError> {
248 self.client.send(data).await
249 }
250
251 pub async fn process_incoming(
254 &self,
255 stream_id: u16,
256 data: Bytes,
257 ) -> Result<(), MultiplexError> {
258 self.client.process_response(stream_id, data).await
259 }
260
261 pub fn in_flight_count(&self) -> usize {
263 self.client.in_flight_count()
264 }
265
266 pub fn can_accept(&self) -> bool {
268 self.client.can_send()
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[tokio::test]
277 async fn test_pipelined_client_creation() {
278 let conn = Arc::new(MultiplexedConnection::new());
279 let client = PipelinedClient::new(conn, 10);
280
281 assert_eq!(client.in_flight_count(), 0);
282 assert!(client.can_send());
283 }
284
285 #[tokio::test]
286 async fn test_pipelined_send() {
287 let conn = Arc::new(MultiplexedConnection::new());
288 let client = PipelinedClient::new(conn.clone(), 10);
289
290 let rx = client.send(Bytes::from("request1")).await.unwrap();
291 assert_eq!(client.in_flight_count(), 1);
292
293 let streams = conn.active_streams().await;
295 assert!(!streams.is_empty());
296
297 let stream_id = streams[0];
298 client
299 .process_response(stream_id, Bytes::from("response1"))
300 .await
301 .unwrap();
302
303 let result = rx.await.unwrap();
305 assert_eq!(result.unwrap(), Bytes::from("response1"));
306 assert_eq!(client.in_flight_count(), 0);
307 }
308
309 #[tokio::test]
310 async fn test_pipelined_batch() {
311 let conn = Arc::new(MultiplexedConnection::new());
312 let client = PipelinedClient::new(conn.clone(), 10);
313
314 let requests = vec![
315 Bytes::from("req1"),
316 Bytes::from("req2"),
317 Bytes::from("req3"),
318 ];
319
320 let receivers = client.send_batch(requests).await.unwrap();
321 assert_eq!(receivers.len(), 3);
322 assert_eq!(client.in_flight_count(), 3);
323 }
324
325 #[tokio::test]
326 async fn test_pipelined_max_in_flight() {
327 let conn = Arc::new(MultiplexedConnection::new());
328 let client = PipelinedClient::new(conn, 2);
329
330 let _rx1 = client.send(Bytes::from("req1")).await.unwrap();
332 let _rx2 = client.send(Bytes::from("req2")).await.unwrap();
333
334 assert_eq!(client.in_flight_count(), 2);
335 assert!(!client.can_send());
336
337 let result = client.send(Bytes::from("req3")).await;
339 assert!(matches!(result, Err(MultiplexError::SendBufferFull)));
340 }
341
342 #[tokio::test]
343 async fn test_pipelined_cancel_all() {
344 let conn = Arc::new(MultiplexedConnection::new());
345 let client = PipelinedClient::new(conn, 10);
346
347 let rx1 = client.send(Bytes::from("req1")).await.unwrap();
348 let rx2 = client.send(Bytes::from("req2")).await.unwrap();
349
350 client.cancel_all().await;
351
352 assert_eq!(client.in_flight_count(), 0);
353
354 let result1 = rx1.await.unwrap();
356 assert!(matches!(result1, Err(MultiplexError::ConnectionClosed)));
357
358 let result2 = rx2.await.unwrap();
359 assert!(matches!(result2, Err(MultiplexError::ConnectionClosed)));
360 }
361
362 #[tokio::test]
363 async fn test_request_pipeline() {
364 let conn = Arc::new(MultiplexedConnection::new());
365 let pipeline = RequestPipeline::new(conn, 10, 100);
366
367 assert!(pipeline.can_accept());
368 assert_eq!(pipeline.in_flight_count(), 0);
369 }
370}