ruststream_fred/pipeline/
message.rs1use std::fmt::{Debug, Formatter};
4use std::sync::Arc;
5use std::sync::atomic::{AtomicBool, Ordering};
6use std::time::Duration;
7
8use ruststream::{AckError, HeaderMap, IncomingMessage, Partitioned};
9
10use super::window::{Form, Round, Window};
11
12pub struct RoundMessage<F: Form> {
45 inner: Option<F::Message>,
47 window: Arc<Window<F>>,
48 round: Round,
49 entered: AtomicBool,
51}
52
53impl<F: Form> Debug for RoundMessage<F>
54where
55 F::Message: Debug,
56{
57 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58 f.debug_struct("RoundMessage")
59 .field("inner", &self.inner)
60 .finish_non_exhaustive()
61 }
62}
63
64impl<F: Form> RoundMessage<F> {
65 pub(crate) const fn new(inner: F::Message, window: Arc<Window<F>>, round: Round) -> Self {
66 Self {
67 inner: Some(inner),
68 window,
69 round,
70 entered: AtomicBool::new(false),
71 }
72 }
73
74 pub(crate) fn inner(&self) -> &F::Message {
80 self.inner
81 .as_ref()
82 .expect("a pipelined delivery is read only before it settles")
83 }
84
85 pub(crate) fn round(&self) -> &Round {
86 &self.round
87 }
88
89 async fn settle(
90 mut self,
91 commit: bool,
92 settle: impl FnOnce(&F, F::Message, &mut Vec<F::Op>) -> Result<(), AckError>,
93 ) -> Result<(), AckError> {
94 #[cfg_attr(not(feature = "testing"), allow(unused_mut))]
95 let mut inner = self
96 .inner
97 .take()
98 .expect("a pipelined delivery settles once");
99 let window = Arc::clone(&self.window);
100 #[cfg(feature = "testing")]
101 window.hold(F::take_flight(&mut inner));
102 window
103 .settle(&self.round, commit, |form, ops| settle(form, inner, ops))
104 .await
105 }
106}
107
108impl<F: Form> Drop for RoundMessage<F> {
109 fn drop(&mut self) {
110 if self.inner.is_some() {
111 self.window.abandon(&self.round);
112 }
113 }
114}
115
116impl<F: Form> Partitioned for RoundMessage<F>
117where
118 F::Message: Partitioned,
119{
120 fn partition_key(&self) -> Option<&[u8]> {
121 Partitioned::partition_key(self.inner())
122 }
123}
124
125impl<F: Form> RoundMessage<F> {
126 fn enter(&self) {
130 if !self.entered.load(Ordering::Relaxed) && !self.entered.swap(true, Ordering::Relaxed) {
132 self.round.enter();
133 }
134 }
135}
136
137impl<F: Form> IncomingMessage for RoundMessage<F> {
138 fn payload(&self) -> &[u8] {
141 self.enter();
142 self.inner().payload()
143 }
144
145 fn headers(&self) -> &HeaderMap {
147 self.enter();
148 self.inner().headers()
149 }
150
151 fn partition_key(&self) -> Option<&[u8]> {
152 self.inner().partition_key()
153 }
154
155 fn redelivery_count(&self) -> Option<u64> {
156 self.inner().redelivery_count()
157 }
158
159 fn supports_nack_after(&self) -> bool {
160 self.inner().supports_nack_after()
161 }
162
163 async fn ack(self) -> Result<(), AckError> {
164 self.settle(true, F::ack).await
165 }
166
167 async fn nack(self, requeue: bool) -> Result<(), AckError> {
168 self.settle(false, move |form, msg, ops| form.nack(msg, requeue, ops))
169 .await
170 }
171
172 async fn nack_after(self, delay: Duration) -> Result<(), AckError> {
173 self.settle(false, move |form, msg, ops| {
174 form.nack_after(msg, delay, ops)
175 })
176 .await
177 }
178}