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 the ticket before the session task dequeues the command cancels
10/// the send: the message never reaches the wire. Fire-and-forget loses quotes
11/// whenever the queue is ahead of the writer — hold every ticket until
12/// [`wait()`](Self::wait) reports the socket-write result.
13#[must_use = "dropping a SendTicket cancels the send if it has not been written yet"]
14pub struct SendTicket {
15    pub(super) rx: oneshot::Receiver<Result<(), ManagedWsError>>,
16}
17
18impl SendTicket {
19    pub async fn wait(self) -> Result<(), ManagedWsError> {
20        match self.rx.await {
21            Ok(result) => result,
22            Err(_) => Err(ManagedWsError::Disconnected),
23        }
24    }
25}
26
27#[derive(Debug, thiserror::Error)]
28#[non_exhaustive]
29pub enum OutboundMessageError {
30    #[error("batch contains {actual} quotes, maximum is {limit}")]
31    BatchTooLarge { actual: usize, limit: usize },
32    #[error("serialized message is {actual} bytes, maximum is {limit}")]
33    MessageTooLarge { actual: usize, limit: usize },
34    #[error("message serialization failed: {0}")]
35    Serialization(#[from] serde_json::Error),
36}
37
38pub(super) fn prepare_outbound(
39    message: &ClientMessage,
40    max_batch_quotes: usize,
41    max_message_size: usize,
42) -> Result<PreparedClientMessage, OutboundMessageError> {
43    if let ClientMessage::BatchQuotes(batch) = message
44        && batch.quotes.len() > max_batch_quotes
45    {
46        return Err(OutboundMessageError::BatchTooLarge {
47            actual: batch.quotes.len(),
48            limit: max_batch_quotes,
49        });
50    }
51    let prepared = PreparedClientMessage::new(message)?;
52    if prepared.len() > max_message_size {
53        return Err(OutboundMessageError::MessageTooLarge {
54            actual: prepared.len(),
55            limit: max_message_size,
56        });
57    }
58    Ok(prepared)
59}