p2panda_stream/spaces/
processor.rs1use std::borrow::Borrow;
4use std::cell::RefCell;
5use std::collections::VecDeque;
6
7use p2panda_auth::traits::Conditions;
8use p2panda_spaces::manager::{Manager, ManagerError};
9use p2panda_spaces::{AuthMessage, Event, SpacesStoreState, StrongRemoveResolver};
10use p2panda_spaces::{Forge, SpacesArgs};
11use p2panda_store::Transaction;
12use p2panda_store::groups::GroupsStore;
13use p2panda_store::key_registry::KeyRegistryStore;
14use p2panda_store::key_secrets::KeySecretsStore;
15use p2panda_store::spaces::{SpacesMessageStore, SpacesStore};
16use tokio::sync::Notify;
17use tracing::trace;
18
19use crate::Processor;
20use crate::spaces::SpacesProcessorArgs;
21
22pub type SpacesManager<S, F, C> = Manager<S, F, C, StrongRemoveResolver<C>>;
23
24pub type SpacesManagerError<F, C> = ManagerError<F, C, StrongRemoveResolver<C>>;
25
26#[derive(Clone)]
27pub enum SpacesResult<C> {
28 Processed { events: Vec<Event<C>> },
29 Ignored,
30}
31
32impl<C> SpacesResult<C> {
33 pub fn was_processed(self) -> bool {
34 match self {
35 Self::Processed { .. } => true,
36 Self::Ignored => false,
37 }
38 }
39}
40
41pub struct Spaces<T, S, F, C> {
43 manager: SpacesManager<S, F, C>,
44 notify: Notify,
45 queue: RefCell<VecDeque<(T, SpacesResult<C>)>>,
46}
47
48impl<T, S, F, C> Spaces<T, S, F, C> {
49 pub fn new(manager: SpacesManager<S, F, C>) -> Self {
50 Self {
51 manager,
52 notify: Notify::new(),
53 queue: RefCell::new(VecDeque::new()),
54 }
55 }
56}
57
58impl<T, S, F, C> Processor<T> for Spaces<T, S, F, C>
59where
60 T: Borrow<SpacesProcessorArgs<C>>,
61 S: Clone
62 + Transaction
63 + SpacesStore<SpacesStoreState<C>>
64 + SpacesMessageStore<SpacesArgs<C>>
65 + GroupsStore<AuthMessage<C>, C>
66 + KeyRegistryStore
67 + KeySecretsStore,
68 F: Forge<C>,
69 C: Conditions,
70{
71 type Output = (T, SpacesResult<C>);
72
73 type Error = (T, SpacesManagerError<F, C>);
74
75 async fn process(&self, input: T) -> Result<(), Self::Error> {
76 let input_args: &SpacesProcessorArgs<C> = input.borrow();
77
78 let result = if let SpacesProcessorArgs::Process { msg } = input_args {
79 let (groups_y, space_y, events) = match self.manager.process(msg).await {
80 Ok(result) => result,
81 Err(err) => return Err((input, err)),
82 };
83
84 if let Some(_groups_y) = groups_y {
85 }
87
88 if let Some(_space_y) = space_y {
89 }
91
92 (input, SpacesResult::Processed { events })
93 } else {
94 trace!("ignore non-spaces operation");
95 (input, SpacesResult::Ignored)
96 };
97
98 self.queue.borrow_mut().push_back(result);
99 self.notify.notify_one();
100
101 Ok(())
102 }
103
104 async fn next(&self) -> Result<Self::Output, Self::Error> {
105 loop {
106 if let Some(item) = self.queue.borrow_mut().pop_front() {
107 return Ok(item);
108 }
109
110 self.notify.notified().await;
111 }
112 }
113}