1use std::any::Any;
18use std::future::Future;
19use std::marker::PhantomData;
20use std::ops::Bound;
21use std::pin::Pin;
22use std::sync::Arc;
23use crate::{Application, state::At, state::Entry, state::Position, state::Recorded};
27
28#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct Cursor(pub u64);
38
39pub struct Batch<A: Application> {
40 pub(crate) rows: Vec<(Cursor, crate::streams::Definition, Position, Arc<dyn Any + Send + Sync>)>,
41 pub(crate) reaches: Cursor,
42 pub(crate) incomplete: Vec<crate::streams::Definition>,
43 pub(crate) application: PhantomData<fn() -> A>,
44}
45
46pub trait JournalConsumer<A: Application>: Send + 'static {
51 fn resume(&self) -> Position;
52
53 fn drain(&mut self, entries: Vec<Arc<Entry<Recorded<A>>>>, applied: Position) -> impl Future<Output = Position> + Send;
54
55 fn flush(&mut self) -> impl Future<Output = ()> + Send {
56 async {}
57 }
58
59 fn redelivered(&mut self, stored: &[(Position, Arc<Vec<u8>>)]) {
60 let _ = stored;
61 }
62}
63
64pub(crate) trait Attached<A: Application>: Send {
65 fn resume(&self) -> Position;
66
67 fn drain(&mut self, entries: Vec<Arc<Entry<Recorded<A>>>>, applied: Position) -> Pin<Box<dyn Future<Output = Position> + Send + '_>>;
68
69 fn flush(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
70
71 fn redelivered(&mut self, stored: &[(Position, Arc<Vec<u8>>)]);
72}
73
74pub trait StreamConsumer<A: Application>: Send + 'static {
75 fn resume(&self) -> Cursor;
76
77 fn selections(&self) -> Vec<crate::streams::Definition> {
78 Vec::new()
79 }
80
81 fn drain(&mut self, batch: Batch<A>) -> impl Future<Output = Cursor> + Send;
82
83 fn flush(&mut self) -> impl Future<Output = ()> + Send {
84 async {}
85 }
86}
87
88pub trait Series<A: Application>: StreamConsumer<A> {
89 fn reader(
90 &mut self, _stream: crate::streams::Definition, _track: &[String], _start: Bound<Position>, _end: Bound<Position>,
91 _limits: crate::streams::ReadLimits,
92 ) -> impl Future<Output = Result<Box<dyn crate::streams::RowSource>, crate::streams::ReadError>> + Send {
93 async { Err(crate::streams::ReadError::Unsupported) }
94 }
95
96 #[allow(clippy::type_complexity)]
100 fn rows(
101 &mut self, stream: crate::streams::Definition, track: &[String], start: Bound<Position>, end: Bound<Position>,
102 ) -> impl Future<Output = Result<Vec<At<Arc<dyn Any + Send + Sync>>>, crate::streams::BeneathWindow>> + Send;
103
104 fn buckets(
105 &mut self, stream: crate::streams::Definition, track: &[String], start: Bound<u64>, end: Bound<u64>, budget: usize,
106 ) -> impl Future<Output = Result<Vec<crate::streams::Bucket>, crate::streams::BeneathWindow>> + Send;
107
108 fn aggregate(
109 &mut self, stream: crate::streams::Definition, track: &[String], start: Bound<u64>, end: Bound<u64>, kind: crate::Aggregate,
110 ) -> impl Future<Output = Result<Vec<crate::streams::Aggregated>, crate::streams::BeneathWindow>> + Send;
111
112 fn seal(&mut self, stream: crate::streams::Definition, track: &[String]) -> impl Future<Output = Position> + Send;
113}
114
115pub(crate) trait Recording<A: Application>: Send {
116 fn resume(&self) -> Cursor;
117
118 fn selections(&self) -> Vec<crate::streams::Definition>;
119
120 fn drain(&mut self, batch: Batch<A>) -> Pin<Box<dyn Future<Output = Cursor> + Send + '_>>;
121
122 fn flush(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
123}
124
125pub(crate) trait Serving<A: Application>: Recording<A> {
126 #[allow(clippy::type_complexity)]
127 fn reader<'read>(
128 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<Position>, end: Bound<Position>,
129 limits: crate::streams::ReadLimits,
130 ) -> Pin<Box<dyn Future<Output = Result<Box<dyn crate::streams::RowSource>, crate::streams::ReadError>> + Send + 'read>>;
131
132 #[allow(clippy::type_complexity)]
133 fn rows<'read>(
134 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<Position>, end: Bound<Position>,
135 ) -> Pin<Box<dyn Future<Output = Result<Vec<At<Arc<dyn Any + Send + Sync>>>, crate::streams::BeneathWindow>> + Send + 'read>>;
136
137 #[allow(clippy::type_complexity)]
138 fn buckets<'read>(
139 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<u64>, end: Bound<u64>, budget: usize,
140 ) -> Pin<Box<dyn Future<Output = Result<Vec<crate::streams::Bucket>, crate::streams::BeneathWindow>> + Send + 'read>>;
141
142 #[allow(clippy::type_complexity)]
143 fn aggregate<'read>(
144 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<u64>, end: Bound<u64>,
145 kind: crate::Aggregate,
146 ) -> Pin<Box<dyn Future<Output = Result<Vec<crate::streams::Aggregated>, crate::streams::BeneathWindow>> + Send + 'read>>;
147
148 fn seal<'read>(
149 &'read mut self, stream: crate::streams::Definition, track: &'read [String],
150 ) -> Pin<Box<dyn Future<Output = Position> + Send + 'read>>;
151}
152
153impl<A: Application, C: JournalConsumer<A>> Attached<A> for C {
156 fn resume(&self) -> Position {
157 JournalConsumer::resume(self)
158 }
159
160 fn drain(&mut self, entries: Vec<Arc<Entry<Recorded<A>>>>, applied: Position) -> Pin<Box<dyn Future<Output = Position> + Send + '_>> {
161 Box::pin(JournalConsumer::drain(self, entries, applied))
162 }
163
164 fn flush(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
165 Box::pin(JournalConsumer::flush(self))
166 }
167
168 fn redelivered(&mut self, stored: &[(Position, Arc<Vec<u8>>)]) {
169 JournalConsumer::redelivered(self, stored);
170 }
171}
172
173impl Cursor {
174 pub const ORIGIN: Self = Self(0);
175}
176
177impl<A: Application> Batch<A> {
178 pub fn reaches(&self) -> Cursor {
179 self.reaches
180 }
181
182 pub fn incomplete(&self) -> &[crate::streams::Definition] {
183 &self.incomplete
184 }
185
186 pub fn publications(&self) -> impl Iterator<Item = (&crate::streams::Definition, Cursor, At<&crate::streams::PublicationRow>)> + '_ {
187 self.rows.iter().filter_map(|(cursor, definition, position, row)| {
188 definition.owner()?;
189 let payload = crate::streams::row_value::<crate::streams::PublicationRow>(row.as_ref())?;
190 Some((definition, *cursor, At { value: payload, position: *position }))
191 })
192 }
193
194 pub fn select<S: crate::streams::Stream<A>>(&self) -> impl Iterator<Item = At<&S>> + '_ {
195 self.rows.iter().filter_map(|(_, definition, position, row)| {
196 if definition.id() != S::ID || definition.version() != S::VERSION {
197 return None;
198 }
199
200 row.downcast_ref::<S>().map(|value| At { value, position: *position })
201 })
202 }
203
204 pub fn select_shared<S: crate::streams::Stream<A>>(&self) -> impl Iterator<Item = At<Arc<S>>> + '_ {
205 self.rows.iter().filter_map(|(_, definition, position, row)| {
206 if definition.id() != S::ID || definition.version() != S::VERSION {
207 return None;
208 }
209 Arc::clone(row).downcast::<S>().ok().map(|value| At { value, position: *position })
210 })
211 }
212}
213
214impl<A: Application, S: Series<A>> Serving<A> for S {
215 #[allow(clippy::type_complexity)]
216 fn reader<'read>(
217 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<Position>, end: Bound<Position>,
218 limits: crate::streams::ReadLimits,
219 ) -> Pin<Box<dyn Future<Output = Result<Box<dyn crate::streams::RowSource>, crate::streams::ReadError>> + Send + 'read>> {
220 Box::pin(Series::reader(self, stream, track, start, end, limits))
221 }
222
223 fn rows<'read>(
224 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<Position>, end: Bound<Position>,
225 ) -> Pin<Box<dyn Future<Output = Result<Vec<At<Arc<dyn Any + Send + Sync>>>, crate::streams::BeneathWindow>> + Send + 'read>> {
226 Box::pin(Series::rows(self, stream, track, start, end))
227 }
228
229 fn buckets<'read>(
230 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<u64>, end: Bound<u64>, budget: usize,
231 ) -> Pin<Box<dyn Future<Output = Result<Vec<crate::streams::Bucket>, crate::streams::BeneathWindow>> + Send + 'read>> {
232 Box::pin(Series::buckets(self, stream, track, start, end, budget))
233 }
234
235 fn aggregate<'read>(
236 &'read mut self, stream: crate::streams::Definition, track: &'read [String], start: Bound<u64>, end: Bound<u64>,
237 kind: crate::Aggregate,
238 ) -> Pin<Box<dyn Future<Output = Result<Vec<crate::streams::Aggregated>, crate::streams::BeneathWindow>> + Send + 'read>> {
239 Box::pin(Series::aggregate(self, stream, track, start, end, kind))
240 }
241
242 fn seal<'read>(
243 &'read mut self, stream: crate::streams::Definition, track: &'read [String],
244 ) -> Pin<Box<dyn Future<Output = Position> + Send + 'read>> {
245 Box::pin(Series::seal(self, stream, track))
246 }
247}
248
249impl<A: Application, C: StreamConsumer<A>> Recording<A> for C {
250 fn resume(&self) -> Cursor {
251 StreamConsumer::resume(self)
252 }
253
254 fn selections(&self) -> Vec<crate::streams::Definition> {
255 StreamConsumer::selections(self)
256 }
257
258 fn drain(&mut self, batch: Batch<A>) -> Pin<Box<dyn Future<Output = Cursor> + Send + '_>> {
259 Box::pin(StreamConsumer::drain(self, batch))
260 }
261
262 fn flush(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
263 Box::pin(StreamConsumer::flush(self))
264 }
265}
266
267