Skip to main content

acta_maker_sdk/ws/managed/
outbound.rs

1use crate::ws::client::PreparedClientMessage;
2use crate::ws::types::ClientMessage;
3use tokio::sync::oneshot;
4
5use super::ManagedWsError;
6
7/// Receipt for a message queued with `try_send`.
8///
9/// Dropping before dequeue cancels the send. Retain the ticket until
10/// [`wait()`](Self::wait) reports the socket-write result, not a server ACK.
11#[must_use = "dropping a SendTicket cancels the send if it has not been written yet"]
12pub struct SendTicket {
13    pub(super) rx: oneshot::Receiver<Result<(), ManagedWsError>>,
14}
15
16impl SendTicket {
17    pub async fn wait(self) -> Result<(), ManagedWsError> {
18        match self.rx.await {
19            Ok(result) => result,
20            Err(_) => Err(ManagedWsError::Disconnected),
21        }
22    }
23}
24
25#[derive(Debug, thiserror::Error)]
26#[non_exhaustive]
27pub enum OutboundMessageError {
28    #[error("batch contains {actual} quotes, maximum is {limit}")]
29    BatchTooLarge { actual: usize, limit: usize },
30    #[error("serialized message is {actual} bytes, maximum is {limit}")]
31    MessageTooLarge { actual: usize, limit: usize },
32    #[error("message serialization failed: {0}")]
33    Serialization(#[from] serde_json::Error),
34}
35
36pub(super) fn prepare_outbound(
37    message: &ClientMessage,
38    max_batch_quotes: usize,
39    max_message_size: usize,
40) -> Result<PreparedClientMessage, OutboundMessageError> {
41    if let ClientMessage::BatchQuotes(batch) = message
42        && batch.quotes.len() > max_batch_quotes
43    {
44        return Err(OutboundMessageError::BatchTooLarge {
45            actual: batch.quotes.len(),
46            limit: max_batch_quotes,
47        });
48    }
49    let prepared = PreparedClientMessage::new(message)?;
50    if prepared.len() > max_message_size {
51        return Err(OutboundMessageError::MessageTooLarge {
52            actual: prepared.len(),
53            limit: max_message_size,
54        });
55    }
56    Ok(prepared)
57}