Implement EventStored infrastructure event that notifies subscribers when an event
is successfully persisted. This enables observability and triggers downstream
workflows (caching, metrics, projections) without coupling to application events.
Changes:
- Add EventStored type to event.go containing EventID, ActorID, Version, Timestamp
- Update InMemoryEventStore with optional EventBus and metrics support via builder methods
- Update JetStreamEventStore with optional EventBus and metrics support via builder methods
- Publish EventStored to __internal__ namespace after successful SaveEvent
- EventStored not published if SaveEvent fails (e.g., version conflict)
- EventStored publishing is optional - stores work without EventBus configured
- Metrics are recorded for each EventStored publication
- Add comprehensive test suite covering all acceptance criteria
Meets acceptance criteria:
- EventStored published after SaveEvent succeeds
- EventStored contains EventID, ActorID, Version, Timestamp
- No EventStored published if SaveEvent fails
- EventBus receives EventStored in same operation
- Metrics increment for each EventStored published
Closes#61
Co-Authored-By: Claude Code <noreply@anthropic.com>
Add ReplayError and ReplayResult types to capture information about
malformed events encountered during replay. This allows callers to
inspect and handle corrupted data rather than having it silently skipped.
Key changes:
- Add ReplayError type with sequence number, raw data, and underlying error
- Add ReplayResult type containing both successfully parsed events and errors
- Add EventStoreWithErrors interface for stores that can report replay errors
- Implement GetEventsWithErrors on JetStreamEventStore
- Update GetEvents to maintain backward compatibility (still skips malformed)
- Add comprehensive unit tests for the new types
This addresses the issue of silent data loss during event-sourced replay
by giving callers visibility into data quality issues.
Closes#39
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Metadata field (map[string]string) to Event struct with omitempty
- Add helper methods for common metadata: SetCorrelationID/GetCorrelationID,
SetCausationID/GetCausationID, SetUserID/GetUserID, SetTraceID/GetTraceID,
SetSpanID/GetSpanID
- Add WithMetadataFrom helper for copying metadata between events
- Add metadata key constants for standard fields
- Add comprehensive unit tests for metadata serialization and helpers
- Add store tests verifying metadata persistence
Closes#7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ErrVersionConflict error type and VersionConflictError for detailed
conflict information
- Implement version validation in InMemoryEventStore.SaveEvent that rejects
events with version <= current latest version
- Implement version validation in JetStreamEventStore.SaveEvent with version
caching for performance
- Add comprehensive tests for version conflict detection including concurrent
writes to same actor
- Document versioning semantics in EventStore interface and CLAUDE.md
This ensures events have monotonically increasing versions per actor and
provides clear error messages for version conflicts, enabling optimistic
concurrency control patterns.
Closes#6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>