fmodel_rust/
materialized_view.rs1use std::future::Future;
2use std::marker::PhantomData;
3
4use crate::view::ViewStateComputation;
5
6pub trait ViewStateRepository<E, S, Error> {
14 fn fetch_state(&self, event: &E) -> impl Future<Output = Result<Option<S>, Error>> + Send;
18 fn save(&self, state: &S) -> impl Future<Output = Result<S, Error>> + Send;
22}
23
24pub struct MaterializedView<S, E, Repository, View, Error>
37where
38 Repository: ViewStateRepository<E, S, Error>,
39 View: ViewStateComputation<E, S>,
40{
41 repository: Repository,
42 view: View,
43 _marker: PhantomData<(S, E, Error)>,
44}
45
46impl<S, E, Repository, View, Error> ViewStateComputation<E, S>
47 for MaterializedView<S, E, Repository, View, Error>
48where
49 Repository: ViewStateRepository<E, S, Error>,
50 View: ViewStateComputation<E, S>,
51{
52 fn compute_new_state(&self, current_state: Option<S>, events: &[&E]) -> S {
54 self.view.compute_new_state(current_state, events)
55 }
56}
57
58impl<S, E, Repository, View, Error> ViewStateRepository<E, S, Error>
59 for MaterializedView<S, E, Repository, View, Error>
60where
61 Repository: ViewStateRepository<E, S, Error> + Sync,
62 View: ViewStateComputation<E, S> + Sync,
63 E: Sync,
64 S: Sync,
65 Error: Sync,
66{
67 async fn fetch_state(&self, event: &E) -> Result<Option<S>, Error> {
69 let state = self.repository.fetch_state(event).await?;
70 Ok(state)
71 }
72 async fn save(&self, state: &S) -> Result<S, Error> {
74 self.repository.save(state).await
75 }
76}
77
78impl<S, E, Repository, View, Error> MaterializedView<S, E, Repository, View, Error>
79where
80 Repository: ViewStateRepository<E, S, Error> + Sync,
81 View: ViewStateComputation<E, S> + Sync,
82 E: Sync,
83 S: Sync,
84 Error: Sync,
85{
86 pub fn new(repository: Repository, view: View) -> Self {
88 MaterializedView {
89 repository,
90 view,
91 _marker: PhantomData,
92 }
93 }
94 pub async fn handle(&self, event: &E) -> Result<S, Error> {
96 let state = self.fetch_state(event).await?;
97 let new_state = self.compute_new_state(state, &[event]);
98 let saved_state = self.save(&new_state).await?;
99 Ok(saved_state)
100 }
101}