pub struct Store<S> { /* private fields */ }Expand description
Shared handle to a RawEventStore backend.
Store wraps the backend in an Arc, making it cheap to clone and
safe to share across tasks. It carries no codec, upcaster, or
aggregate binding — it is just a database handle.
Use repository() to obtain a
RepositoryBuilder, then
configure a codec and upcaster before calling .build().
§Example
// Open flows left-to-right; `.into_store()` is the de-nested `Store::new`.
let store = FjallStore::builder("path").open()?.into_store();
// One per-aggregate facade per aggregate; the store is the shared substrate.
let orders = store.repository::<Order>().codec(OrderCodec).build();
let users = store.repository::<User>().codec(UserCodec).build();Implementations§
Source§impl<S: RawEventStore> Store<S>
impl<S: RawEventStore> Store<S>
Sourcepub fn repository<A>(&self) -> RepositoryBuilder<S, NeedsCodec, A>
pub fn repository<A>(&self) -> RepositoryBuilder<S, NeedsCodec, A>
Start building a repository facade for aggregate A over this store.
Name the aggregate once here (store.repository::<Order>()); the
resulting EventStore<S, C, A> then implements Repository<A> for
exactly that A, so load/save infer the aggregate with no
per-call annotation. The store itself stays multi-aggregate — mint one
facade per aggregate type.
The builder starts with NeedsCodec in every feature
configuration — set a codec with .codec(),
or, under the json feature, the .json()
convenience, before calling .build(). Keeping this return type feature
independent is what makes json purely additive (issue #211): a
transitive dependency enabling json can never flip this signature out
from under code that spelled NeedsCodec.
§Example
let store = Store::new(backend);
// Custom codec:
let orders = store.repository::<Order>().codec(MyCodec).build();
let order = orders.load(id).await?; // AggregateRoot<Order> — inferred
// Built-in JSON codec (requires the `json` feature):
let orders = store.repository::<Order>().json().build();Source§impl<S> Store<S>
impl<S> Store<S>
Sourcepub fn raw(&self) -> &S
pub fn raw(&self) -> &S
Borrow the underlying raw store.
The escape hatch for users who need the substrate directly — when
the Repository facade’s load / save isn’t
flexible enough (e.g. you want to filter, peek, branch, or chain
custom combinators during load). Hand the borrowed &S to
RawEventStore::read_stream / RawEventStore::append and
compose your own chain via futures::StreamExt /
futures::TryStreamExt.
Users who just want “load this aggregate” should stay on the facade.
§Example
Substrate-path read: convert the adapter error eagerly and drive a custom fold.
use futures::TryStreamExt;
use mnesis_store::{RawEventStore, Store, StreamKey};
async fn count_events<S: RawEventStore>(
store: &Store<S>,
id: &StreamKey,
from: mnesis::Version,
) -> Result<usize, MyError> {
let stream = store.raw().read_stream(id, from).await.map_err(MyError::Adapter)?;
stream.map_err(MyError::Adapter).try_fold(0usize, |acc, _| async move { Ok(acc + 1) }).await
}Trait Implementations§
Source§impl<S: AtomicAppend> AtomicAppend for Store<S>
Store<S> forwards AtomicAppend to its inner backend (issue #247). With
Store<S> already a RawEventStore, this gives it EventImporter for
free via the blanket impl below — so a handle holder can store.import(..)
without .raw().
impl<S: AtomicAppend> AtomicAppend for Store<S>
Store<S> forwards AtomicAppend to its inner backend (issue #247). With
Store<S> already a RawEventStore, this gives it EventImporter for
free via the blanket impl below — so a handle holder can store.import(..)
without .raw().
Source§async fn atomic_append_many(
&self,
writes: &[PlannedAppend],
) -> Result<Option<Self::AllPosition>, AtomicAppendError<Self::Error>>
async fn atomic_append_many( &self, writes: &[PlannedAppend], ) -> Result<Option<Self::AllPosition>, AtomicAppendError<Self::Error>>
Source§impl<S: RawEventStore> RawEventStore for Store<S>
Store<S> is itself a RawEventStore, forwarding every method to its
inner backend.
impl<S: RawEventStore> RawEventStore for Store<S>
Store<S> is itself a RawEventStore, forwarding every method to its
inner backend.
This makes the handle the front door: store.append(..) / read_stream /
read_all work directly, and — because EventExporter and
EventImporter are blanket-impl’d for every RawEventStore (and
RawEventStore + AtomicAppend) — store.export_stream(..) /
store.import(..) come for free once Store<S> also forwards
StreamLister / AtomicAppend (in the export / import modules). So
a Store<S> holder never needs .raw() to back up or restore, and a
Store<S> is substitutable wherever a RawEventStore-bounded value is
expected. .raw() remains the escape hatch for reaching the concrete &S.
Source§type Error = <S as RawEventStore>::Error
type Error = <S as RawEventStore>::Error
Source§type AllPosition = <S as RawEventStore>::AllPosition
type AllPosition = <S as RawEventStore>::AllPosition
Source§type AllStream = <S as RawEventStore>::AllStream
type AllStream = <S as RawEventStore>::AllStream
$all) read. Read moreSource§async fn append(
&self,
id: &StreamKey,
expected_version: Option<Version>,
envelopes: PendingBatch<'_>,
) -> Result<Self::AllPosition, AppendError<Self::Error>>
async fn append( &self, id: &StreamKey, expected_version: Option<Version>, envelopes: PendingBatch<'_>, ) -> Result<Self::AllPosition, AppendError<Self::Error>>
Source§async fn read_stream(
&self,
id: &StreamKey,
from: Version,
) -> Result<Self::Stream, Self::Error>
async fn read_stream( &self, id: &StreamKey, from: Version, ) -> Result<Self::Stream, Self::Error>
Source§async fn read_all(
&self,
from: Option<Self::AllPosition>,
) -> Result<Self::AllStream, Self::Error>
async fn read_all( &self, from: Option<Self::AllPosition>, ) -> Result<Self::AllStream, Self::Error>
AllPosition. Read moreSource§impl<S: StreamLister> StreamLister for Store<S>
Store<S> forwards StreamLister to its inner backend (issue #247), so a
handle holder can store.list_streams() without .raw(). EventExporter
then applies to Store<S> via the blanket impl above (Store<S> is itself a
RawEventStore).
impl<S: StreamLister> StreamLister for Store<S>
Store<S> forwards StreamLister to its inner backend (issue #247), so a
handle holder can store.list_streams() without .raw(). EventExporter
then applies to Store<S> via the blanket impl above (Store<S> is itself a
RawEventStore).
Source§type StreamList = <S as StreamLister>::StreamList
type StreamList = <S as StreamLister>::StreamList
Source§async fn list_streams(&self) -> Result<Self::StreamList, Self::Error>
async fn list_streams(&self) -> Result<Self::StreamList, Self::Error>
Auto Trait Implementations§
impl<S> Freeze for Store<S>
impl<S> RefUnwindSafe for Store<S>where
S: RefUnwindSafe,
impl<S> Send for Store<S>
impl<S> Sync for Store<S>
impl<S> Unpin for Store<S>
impl<S> UnsafeUnpin for Store<S>
impl<S> UnwindSafe for Store<S>where
S: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<S> EventExporter for Swhere
S: RawEventStore,
impl<S> EventExporter for Swhere
S: RawEventStore,
Source§type ExportStream = <S as RawEventStore>::Stream
type ExportStream = <S as RawEventStore>::Stream
Source§fn export_stream(
&self,
id: &StreamKey,
from: Version,
) -> impl Future<Output = Result<<S as EventExporter>::ExportStream, <S as RawEventStore>::Error>> + Send
fn export_stream( &self, id: &StreamKey, from: Version, ) -> impl Future<Output = Result<<S as EventExporter>::ExportStream, <S as RawEventStore>::Error>> + Send
id, starting at from (inclusive).Source§impl<S> EventImporter for Swhere
S: RawEventStore + AtomicAppend,
impl<S> EventImporter for Swhere
S: RawEventStore + AtomicAppend,
Source§async fn import<R>(
&self,
sections: &[StreamSection],
route: R,
atomicity: Atomicity,
) -> Result<ImportReport, ImportError<<S as RawEventStore>::Error>>
async fn import<R>( &self, sections: &[StreamSection], route: R, atomicity: Atomicity, ) -> Result<ImportReport, ImportError<<S as RawEventStore>::Error>>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.