pub struct EventStream { /* private fields */ }Expand description
Event Stream aggregate enforcing gapless version numbers
Inspired by SierraDB’s watermark pattern for consistent event sourcing. Ensures no gaps in version sequences, critical for proper event replay.
§SierraDB Pattern
- Watermark tracks “highest continuously confirmed sequence”
- Prevents gaps that would break event sourcing guarantees
- Uses optimistic locking for concurrency control
§Invariants
- Versions start at 1 and increment sequentially
- No gaps allowed in version sequence
- Watermark <= max version always
- All versions below watermark are confirmed (gapless)
Implementations§
Source§impl EventStream
impl EventStream
Sourcepub fn reconstruct(
stream_id: EntityId,
partition_key: PartitionKey,
current_version: u64,
watermark: u64,
events: Vec<Event>,
expected_version: Option<u64>,
created_at: DateTime<Utc>,
updated_at: DateTime<Utc>,
) -> Result<Self>
pub fn reconstruct( stream_id: EntityId, partition_key: PartitionKey, current_version: u64, watermark: u64, events: Vec<Event>, expected_version: Option<u64>, created_at: DateTime<Utc>, updated_at: DateTime<Utc>, ) -> Result<Self>
Reconstruct an EventStream from persistent storage
Used by repository implementations to restore streams from database. Bypasses validation since data is already validated at creation time.
§Arguments
stream_id: Entity ID of the streampartition_key: Pre-computed partition assignmentcurrent_version: Latest version numberwatermark: Highest continuously confirmed versionevents: All events in the streamexpected_version: Optional optimistic lock versioncreated_at: Stream creation timestampupdated_at: Last modification timestamp
Sourcepub fn append_event(&mut self, event: Event) -> Result<u64>
pub fn append_event(&mut self, event: Event) -> Result<u64>
Append an event with optimistic locking
§SierraDB Pattern
- Checks expected_version matches current_version
- Prevents concurrent modification conflicts
- Ensures gapless version sequence
Sourcepub fn expect_version(&mut self, version: u64)
pub fn expect_version(&mut self, version: u64)
Set expected version for next append (optimistic locking)
Sourcepub fn clear_expected_version(&mut self)
pub fn clear_expected_version(&mut self)
Clear expected version
Sourcepub fn events_from(&self, from_version: u64) -> Vec<&Event>
pub fn events_from(&self, from_version: u64) -> Vec<&Event>
Get events from version (inclusive)
Sourcepub fn is_gapless(&self) -> bool
pub fn is_gapless(&self) -> bool
Check if stream has gapless versions up to watermark
pub fn stream_id(&self) -> &EntityId
pub fn partition_key(&self) -> &PartitionKey
pub fn current_version(&self) -> u64
pub fn watermark(&self) -> u64
pub fn event_count(&self) -> usize
pub fn created_at(&self) -> DateTime<Utc>
pub fn updated_at(&self) -> DateTime<Utc>
pub fn expected_version(&self) -> Option<u64>
Sourcepub fn tenant_id(&self) -> Option<&TenantId>
pub fn tenant_id(&self) -> Option<&TenantId>
Get the tenant ID for this stream
Returns the tenant_id from the first event, or None if the stream is empty. All events in a stream should belong to the same tenant.
Sourcepub fn has_consistent_tenant(&self) -> bool
pub fn has_consistent_tenant(&self) -> bool
Validate that all events in the stream belong to the same tenant
Returns true if the stream is empty or all events have the same tenant_id. This is a safety check to detect tenant isolation violations.
Sourcepub fn validate_event_tenant(&self, event: &Event) -> Result<()>
pub fn validate_event_tenant(&self, event: &Event) -> Result<()>
Validate that an event belongs to this stream’s tenant
Returns an error if:
- The stream has events and the new event’s tenant doesn’t match
This ensures tenant isolation at the stream level.
Sourcepub fn append_event_with_tenant_check(&mut self, event: Event) -> Result<u64>
pub fn append_event_with_tenant_check(&mut self, event: Event) -> Result<u64>
Append an event with tenant validation
Like append_event, but also validates tenant consistency.
Prevents cross-tenant event appends for security.
Trait Implementations§
Source§impl Clone for EventStream
impl Clone for EventStream
Source§fn clone(&self) -> EventStream
fn clone(&self) -> EventStream
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for EventStream
impl Debug for EventStream
Source§impl<'de> Deserialize<'de> for EventStream
impl<'de> Deserialize<'de> for EventStream
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for EventStream
impl RefUnwindSafe for EventStream
impl Send for EventStream
impl Sync for EventStream
impl Unpin for EventStream
impl UnwindSafe for EventStream
Blanket Implementations§
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<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> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more