use eventcore_types::{Projector, StreamPosition};
use std::convert::Infallible;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub struct EventCollector<E> {
events: Arc<Mutex<Vec<E>>>,
}
impl<E> EventCollector<E> {
pub fn new(storage: Arc<Mutex<Vec<E>>>) -> Self {
Self { events: storage }
}
pub fn events(&self) -> Vec<E>
where
E: Clone,
{
self.events
.lock()
.expect("EventCollector mutex poisoned - a test panicked while holding the lock")
.clone()
}
}
impl<E: Send + 'static> Projector for EventCollector<E> {
type Event = E;
type Error = Infallible;
type Context = ();
fn apply(
&mut self,
event: Self::Event,
_position: StreamPosition,
_ctx: &mut Self::Context,
) -> Result<(), Self::Error> {
self.events
.lock()
.expect("EventCollector mutex poisoned - a test panicked while holding the lock")
.push(event);
Ok(())
}
fn name(&self) -> &str {
"event-collector"
}
}
#[cfg(test)]
mod tests {
use crate::event_collector::EventCollector;
#[derive(Debug, Clone, PartialEq)]
struct TestEvent {
id: u32,
}
#[test]
fn new_collector_has_empty_events() {
use std::sync::{Arc, Mutex};
let storage: Arc<Mutex<Vec<TestEvent>>> = Arc::new(Mutex::new(Vec::new()));
let collector = EventCollector::new(storage);
let events = collector.events();
assert!(events.is_empty());
}
#[test]
fn collects_event_via_projector_apply() {
use eventcore_types::{Projector, StreamPosition};
use std::sync::{Arc, Mutex};
use uuid::Uuid;
let storage: Arc<Mutex<Vec<TestEvent>>> = Arc::new(Mutex::new(Vec::new()));
let mut collector = EventCollector::new(storage);
let event = TestEvent { id: 42 };
let position = StreamPosition::new(Uuid::nil());
let result = collector.apply(event.clone(), position, &mut ());
assert!(result.is_ok());
assert_eq!(collector.events(), vec![event]);
}
#[test]
fn events_accessible_after_collector_moved() {
use eventcore_types::{Projector, StreamPosition};
use std::sync::{Arc, Mutex};
use uuid::Uuid;
let storage: Arc<Mutex<Vec<TestEvent>>> = Arc::new(Mutex::new(Vec::new()));
let collector = EventCollector::new(storage.clone());
let mut moved_collector = collector;
let event = TestEvent { id: 99 };
let position = StreamPosition::new(Uuid::nil());
let _ = moved_collector.apply(event.clone(), position, &mut ());
let events = storage.lock().unwrap();
assert_eq!(*events, vec![event]);
}
#[test]
fn projector_name_is_event_collector() {
use eventcore_types::Projector;
use std::sync::{Arc, Mutex};
let storage: Arc<Mutex<Vec<TestEvent>>> = Arc::new(Mutex::new(Vec::new()));
let collector = EventCollector::new(storage);
assert_eq!(collector.name(), "event-collector");
}
}