use std::sync::Arc;
use batpak::coordinate::Coordinate;
use batpak::event::EventKind;
use batpak::store::{AppendReceipt, Open, Store};
use serde::{Serialize, Serializer};
use crate::effect_backend::{EffectBackend, EffectError, TypedEffectEvent};
pub struct StoreEffectBackend {
store: Arc<Store<Open>>,
coordinate: Coordinate,
}
impl StoreEffectBackend {
#[must_use]
pub fn new(store: Arc<Store<Open>>, coordinate: Coordinate) -> Self {
Self { store, coordinate }
}
}
impl EffectBackend for StoreEffectBackend {
fn append_event(&mut self, kind: EventKind, payload: &[u8]) -> Result<(), EffectError> {
self.store
.append(&self.coordinate, kind, &RawPayload(payload))
.map(|_receipt| ())
.map_err(|error| EffectError::new(error.to_string()))
}
fn append_typed_event<'event>(
&mut self,
coordinate: &Coordinate,
event: TypedEffectEvent<'event>,
) -> Result<AppendReceipt, EffectError> {
event
.append_to_store(&self.store, coordinate)
.map_err(|error| EffectError::new(error.to_string()))
}
fn read_event(&mut self, event_category: &str) -> Result<(), EffectError> {
let _ = event_category;
let stream = self.store.by_entity(self.coordinate.entity());
if let Some(entry) = stream.last() {
self.store
.read_raw(entry.event_id())
.map(|_event| ())
.map_err(|error| EffectError::new(error.to_string()))?;
}
Ok(())
}
fn query_projection(&mut self, projection_id: &str) -> Result<(), EffectError> {
let _ = projection_id;
let _hits = self.store.by_scope(self.coordinate.scope());
Ok(())
}
}
struct RawPayload<'a>(&'a [u8]);
impl Serialize for RawPayload<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(self.0)
}
}