Skip to main content

harmos_runtime/storage/
consumer.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10/* === Modules === */
11
12/* === Re-Exports === */
13
14/* === Imports === */
15
16// Standard Library Imports
17use std::any::Any;
18use std::future::Future;
19use std::marker::PhantomData;
20use std::ops::Bound;
21use std::pin::Pin;
22use std::sync::Arc;
23// Third Party Imports
24
25// Local Imports
26use crate::{Application, state::At, state::Entry, state::Position, state::Recorded};
27
28/* === Constants === */
29
30/* === Macros === */
31
32/* === Type Aliases === */
33
34/* === Structs === */
35
36#[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
46/* === Enums === */
47
48/* === Traits === */
49
50pub 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    // Rows are spelled out rather than aliased: the census is the list of
97    // names an author learns, and an erased row belongs to this signature
98    // rather than beside them.
99    #[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
153/* === Implementations === */
154
155impl<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/* === Public Functions === */
268
269/* === Private Functions === */
270
271/* === Tests === */