Documentation
¶
Overview ¶
Package eventstore provides core abstractions and types for event sourcing with Dynamic Event Streams.
This package defines the fundamental interfaces and types used across different event store implementations, including filters, storable events, and common error definitions.
The event store supports dynamic filtering of events based on:
- Event types
- JSON payload predicates
- Time ranges (occurred from/until)
Key types:
- Filter: Defines criteria for querying events
- StorableEvent: Represents an event that can be stored and retrieved
- StorableEvents: Collection of storable events
Common usage pattern:
// Create a filter for multiple event types with a predicate filter := BuildEventFilter(). Matching(). AnyEventTypeOf( core.BookCopyLentToReaderEventType, core.BookCopyReturnedByReaderEventType). AndAnyPredicateOf(P("BookID", bookID.String())). Finalize() events, maxSeq, err := store.Query(ctx, filter) if err != nil { // handle error } newEvent, err := eventstore.BuildStorableEvent(eventType, time.Now(), payload, metadata) if err != nil { // handle error } err = store.Append(ctx, filter, maxSeq, newEvent)
Index ¶
- Constants
- Variables
- func WithEventualConsistency(ctx context.Context) context.Context
- func WithStrongConsistency(ctx context.Context) context.Context
- type CompletedFilterItemBuilder
- type CompletedFilterItemBuilderWithOccurredFrom
- type CompletedFilterItemBuilderWithOccurredFromToUntil
- type CompletedFilterItemBuilderWithOccurredUntil
- type CompletedFilterItemBuilderWithSequenceNumber
- type ConsistencyLevel
- type ContextualLogger
- type ContextualMetricsCollector
- type EmptyFilterItemBuilder
- type Filter
- type FilterBuilder
- type FilterEventTypeString
- type FilterItem
- type FilterItemBuilderLackingEventTypes
- type FilterItemBuilderLackingPredicates
- type FilterKeyString
- type FilterPredicate
- type FilterValString
- type Logger
- type MaxSequenceNumberUint
- type MetricsCollector
- type SequenceFilteringCapable
- type SequenceFilteringIncompatible
- type Snapshot
- type SpanContext
- type StorableEvent
- type StorableEvents
- type TracingCollector
Constants ¶
const ConsistencyLevelKey contextKey = "eventstore.consistency_level"
ConsistencyLevelKey is the context key used to store consistency level preferences.
Variables ¶
var ( // ErrEmptyEventsTableName is returned when an empty table name is provided during event store configuration. ErrEmptyEventsTableName = errors.New("events table name must not be empty") // ErrConcurrencyConflict is returned when an optimistic concurrency check fails during event appending. ErrConcurrencyConflict = errors.New("concurrency error, no rows were affected") // ErrCantBuildQueryForZeroEvents is returned when zero events were supplied to build an append query. ErrCantBuildQueryForZeroEvents = errors.New("can't build query for zero events") // ErrNilDatabaseConnection is returned when a nil database connection is provided to event store constructors. ErrNilDatabaseConnection = errors.New("database connection must not be nil") // ErrQueryingEventsFailed is returned when the underlying database query operation fails during event retrieval. ErrQueryingEventsFailed = errors.New("querying events failed") // ErrScanningDBRowFailed is returned when database row scanning fails during event retrieval. ErrScanningDBRowFailed = errors.New("scanning db row failed") // ErrBuildingStorableEventFailed is returned when construction of a StorableEvent from database data fails. ErrBuildingStorableEventFailed = errors.New("building storable event failed") // ErrAppendingEventFailed is returned when the underlying database execution fails during event appending. ErrAppendingEventFailed = errors.New("appending the event failed") // ErrGettingRowsAffectedFailed is returned when retrieving the affected row count after database execution fails. ErrGettingRowsAffectedFailed = errors.New("getting rows affected failed") // ErrBuildingQueryFailed is returned when SQL query construction fails during event store operations. ErrBuildingQueryFailed = errors.New("building the query failed") // ErrRowIterationFailed is returned when iterating over database result rows fails during event retrieval. ErrRowIterationFailed = errors.New("database rows iteration failed") )
var ( // ErrInvalidSnapshotJSON is returned when snapshot JSON data is malformed or invalid. ErrInvalidSnapshotJSON = errors.New("snapshot json is not valid") // ErrEmptyProjectionType is returned when an empty projection type is provided. ErrEmptyProjectionType = errors.New("projection type must not be empty") // ErrEmptyFilterHash is returned when an empty filter hash is provided. ErrEmptyFilterHash = errors.New("filter hash must not be empty") // ErrSavingSnapshotFailed is returned when the snapshot save operation fails. ErrSavingSnapshotFailed = errors.New("saving snapshot failed") // ErrLoadingSnapshotFailed is returned when the snapshot load operation fails. ErrLoadingSnapshotFailed = errors.New("loading snapshot failed") // ErrDeletingSnapshotFailed is returned when the snapshot delete operation fails. ErrDeletingSnapshotFailed = errors.New("deleting snapshot failed") )
var ( // ErrInvalidPayloadJSON is returned when payload JSON is malformed or invalid. ErrInvalidPayloadJSON = errors.New("payload json is not valid") // ErrInvalidMetadataJSON is returned when metadata JSON is malformed or invalid. ErrInvalidMetadataJSON = errors.New("metadata json is not valid") )
Functions ¶
func WithEventualConsistency ¶
WithEventualConsistency returns a context that signals EventStore operations may use replica databases for eventual consistency, trading consistency for performance.
This is typically used by pure query handlers that can tolerate slightly stale data in exchange for better performance and reduced primary database load.
Example usage:
ctx = eventstore.WithEventualConsistency(ctx) events, maxSeq, err := eventStore.Query(ctx, filter)
func WithStrongConsistency ¶
WithStrongConsistency returns a context that signals EventStore operations should use the primary database for strong consistency guarantees.
This is typically used by command handlers that perform read-check-write patterns and need to ensure they see the most recent state.
Example usage:
ctx = eventstore.WithStrongConsistency(ctx) events, maxSeq, err := eventStore.Query(ctx, filter)
Types ¶
type CompletedFilterItemBuilder ¶
type CompletedFilterItemBuilder interface { // OccurredFrom sets the lower boundary for occurredAt (including this timestamp) for the whole Filter. OccurredFrom(occurredAtFrom time.Time) CompletedFilterItemBuilderWithOccurredFrom // OccurredUntil sets the upper boundary for occurredAt (including this timestamp) for the whole Filter. // // Currently, there is NO check if OccurredUntil is later than OccurredFrom! OccurredUntil(occurredAtUntil time.Time) CompletedFilterItemBuilderWithOccurredUntil // WithSequenceNumberHigherThan sets the sequence number boundary (exclusive) for the whole Filter. // This makes time boundaries unavailable (mutually exclusive). WithSequenceNumberHigherThan(sequenceNumber uint) CompletedFilterItemBuilderWithSequenceNumber // OrMatching finalizes the current FilterItem and starts a new one. OrMatching() EmptyFilterItemBuilder // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
CompletedFilterItemBuilder represents a FilterItem with both event types and predicates. You can set time boundaries, add more items, or finalize the filter.
type CompletedFilterItemBuilderWithOccurredFrom ¶
type CompletedFilterItemBuilderWithOccurredFrom interface { // AndOccurredUntil sets the upper boundary for occurredAt (including this timestamp) for the whole Filter. // // Currently, there is NO check if AndOccurredUntil is later than OccurredFrom! AndOccurredUntil(occurredAtUntil time.Time) CompletedFilterItemBuilderWithOccurredFromToUntil // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
CompletedFilterItemBuilderWithOccurredFrom represents a completed FilterItem with a lower time boundary set. You can optionally add an upper time boundary or finalize the filter.
type CompletedFilterItemBuilderWithOccurredFromToUntil ¶
type CompletedFilterItemBuilderWithOccurredFromToUntil interface { // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
CompletedFilterItemBuilderWithOccurredFromToUntil represents a completed FilterItem with both time boundaries set. You can only finalize the filter at this stage.
type CompletedFilterItemBuilderWithOccurredUntil ¶
type CompletedFilterItemBuilderWithOccurredUntil interface { // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
CompletedFilterItemBuilderWithOccurredUntil represents a completed FilterItem with an upper time boundary set. You can only finalize the filter at this stage.
type CompletedFilterItemBuilderWithSequenceNumber ¶
type CompletedFilterItemBuilderWithSequenceNumber interface { // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
CompletedFilterItemBuilderWithSequenceNumber represents a completed FilterItem with a sequence boundary set. You can only finalize the filter at this stage.
type ConsistencyLevel ¶
type ConsistencyLevel int
ConsistencyLevel defines the consistency requirements for EventStore operations.
const ( // StrongConsistency requires reads from the primary database to ensure // read-after-write consistency. This is the default for EventStore operations // to provide safety in event sourcing scenarios where command handlers need // to see their own writes immediately. StrongConsistency ConsistencyLevel = iota // EventualConsistency allows reads from replica databases, trading consistency // for performance. Suitable for pure query operations that can tolerate // slightly stale data in exchange for a reduced load on the primary database. EventualConsistency )
func GetConsistencyLevel ¶
func GetConsistencyLevel(ctx context.Context) ConsistencyLevel
GetConsistencyLevel extracts the consistency level from the context. If no consistency level is set, it returns StrongConsistency as the safe default for event sourcing scenarios.
func (ConsistencyLevel) String ¶
func (c ConsistencyLevel) String() string
String provides a string representation of ConsistencyLevel for logging and debugging.
type ContextualLogger ¶
type ContextualLogger interface { DebugContext(ctx context.Context, msg string, args ...any) InfoContext(ctx context.Context, msg string, args ...any) WarnContext(ctx context.Context, msg string, args ...any) ErrorContext(ctx context.Context, msg string, args ...any) }
ContextualLogger interface for context-aware logging with automatic trace correlation. This interface follows the same dependency-free pattern as MetricsCollector and TracingCollector, allowing users to integrate with any logging backend (OpenTelemetry, structured loggers, etc.) that supports context-based correlation and automatic trace/span ID inclusion.
type ContextualMetricsCollector ¶
type ContextualMetricsCollector interface { MetricsCollector RecordDurationContext(ctx context.Context, metric string, duration time.Duration, labels map[string]string) IncrementCounterContext(ctx context.Context, metric string, labels map[string]string) RecordValueContext(ctx context.Context, metric string, value float64, labels map[string]string) }
ContextualMetricsCollector extends MetricsCollector with context-aware methods for better tracing integration. Implementations can use the context for trace correlation, span propagation, and other contextual metadata. This interface is optional - EventStore will use context-aware methods when available, falling back to the base MetricsCollector interface for backward compatibility.
type EmptyFilterItemBuilder ¶
type EmptyFilterItemBuilder interface { // AnyEventTypeOf adds one or multiple EventTypes to the current FilterItem. // // It sanitizes the input: // - removing empty EventTypes ("") // - sorting the EventTypes // - removing duplicate EventTypes AnyEventTypeOf(eventType FilterEventTypeString, eventTypes ...FilterEventTypeString) FilterItemBuilderLackingPredicates // AnyPredicateOf adds one or multiple FilterPredicate(s) to the current FilterItem. // // It sanitizes the input: // - removing empty/partial FilterPredicate(s) (key or val is "") // - sorting the FilterPredicate(s) // - removing duplicate FilterPredicate(s) AnyPredicateOf(predicate FilterPredicate, predicates ...FilterPredicate) FilterItemBuilderLackingEventTypes // AllPredicatesOf adds one or multiple FilterPredicate(s) to the current FilterItem expecting ALL predicates to match. // // It sanitizes the input: // - removing empty/partial FilterPredicate(s) (key or val is "") // - sorting the FilterPredicate(s) // - removing duplicate FilterPredicate(s) AllPredicatesOf(predicate FilterPredicate, predicates ...FilterPredicate) FilterItemBuilderLackingEventTypes }
EmptyFilterItemBuilder represents the initial state when starting a new FilterItem. At this stage, you must add either event types or predicates to proceed.
type Filter ¶
type Filter struct {
// contains filtered or unexported fields
}
Filter represents a complete event filter with FilterItems and optional time or sequence boundaries. Multiple FilterItems are combined with OR logic, while predicates within items follow configurable AND/OR logic based on AllPredicatesMustMatch.
func (Filter) Hash ¶
Hash returns a deterministic SHA256 hash of the filter for snapshot identification. The hash includes all filter components: items, time boundaries, and sequence boundaries.
func (Filter) Items ¶
func (f Filter) Items() []FilterItem
Items returns the collection of FilterItems that define the filter criteria.
func (Filter) OccurredFrom ¶
OccurredFrom returns the lower time boundary for event filtering (inclusive).
func (Filter) OccurredUntil ¶
OccurredUntil returns the upper time boundary for event filtering (inclusive).
func (Filter) ReopenForSequenceFiltering ¶
func (f Filter) ReopenForSequenceFiltering() interface{}
ReopenForSequenceFiltering attempts to reopen this filter for sequence number filtering. Returns either SequenceFilteringCapable (if no time boundaries are set) or SequenceFilteringIncompatible (if time boundaries conflict). This provides compile-time safety - you can only call WithSequenceNumberHigherThan on the returned interface if the filter is compatible.
func (Filter) SequenceNumberHigherThan ¶
SequenceNumberHigherThan returns the minimum sequence number for event filtering (exclusive).
type FilterBuilder ¶
type FilterBuilder interface { // Matching starts a new FilterItem. Matching() EmptyFilterItemBuilder // MatchingAnyEvent directly creates an empty Filter. // WARNING: This returns ALL events and should not be used in production. MatchingAnyEvent() Filter // OccurredFrom sets the lower boundary for occurredAt (including this timestamp) for the whole Filter. OccurredFrom(occurredAtFrom time.Time) CompletedFilterItemBuilderWithOccurredFrom // OccurredUntil sets the upper boundary for occurredAt (including this timestamp) for the whole Filter. // // Currently, there is NO check if OccurredUntil is later than OccurredFrom! OccurredUntil(occurredAtUntil time.Time) CompletedFilterItemBuilderWithOccurredUntil // WithSequenceNumberHigherThan sets the sequence number boundary (exclusive) for the whole Filter. // This makes time boundaries unavailable (mutually exclusive). WithSequenceNumberHigherThan(sequenceNumber uint) CompletedFilterItemBuilderWithSequenceNumber }
FilterBuilder builds generic event filters for database-specific query implementations. It enforces useful filter combinations for event-sourced workflows, supporting event types, JSON payload predicates, and time ranges. Complex combinations are supported through multiple FilterItems with OR logic between items and configurable AND/OR logic within items.
func BuildEventFilter ¶
func BuildEventFilter() FilterBuilder
BuildEventFilter creates a FilterBuilder which must eventually be finalized with Finalize() or MatchingAnyEvent(). Note: MatchingAnyEvent() returns ALL events and should not be used in production.
type FilterEventTypeString ¶
type FilterEventTypeString = string
FilterEventTypeString represents an event type identifier used in filter criteria.
type FilterItem ¶
type FilterItem struct {
// contains filtered or unexported fields
}
FilterItem represents a single filter condition combining event types and JSON predicates. Event types are always combined with OR logic, while predicates follow AND / OR logic based on the AllPredicatesMustMatch flag.
func (FilterItem) AllPredicatesMustMatch ¶
func (fi FilterItem) AllPredicatesMustMatch() bool
AllPredicatesMustMatch returns true if all predicates must match (AND logic), false if any predicate can match (OR logic).
func (FilterItem) EventTypes ¶
func (fi FilterItem) EventTypes() []FilterEventTypeString
EventTypes returns the event type identifiers for this filter item.
func (FilterItem) Predicates ¶
func (fi FilterItem) Predicates() []FilterPredicate
Predicates returns the JSON predicates for this filter item.
type FilterItemBuilderLackingEventTypes ¶
type FilterItemBuilderLackingEventTypes interface { // AndAnyEventTypeOf adds one or multiple EventTypes to the current FilterItem. // // It sanitizes the input: // - removing empty EventTypes ("") // - sorting the EventTypes // - removing duplicate EventTypes AndAnyEventTypeOf(eventType FilterEventTypeString, eventTypes ...FilterEventTypeString) CompletedFilterItemBuilder // OccurredFrom sets the lower boundary for occurredAt (including this timestamp) for the whole Filter. OccurredFrom(occurredAtFrom time.Time) CompletedFilterItemBuilderWithOccurredFrom // OccurredUntil sets the upper boundary for occurredAt (including this timestamp) for the whole Filter. // // Currently, there is NO check if OccurredUntil is later than OccurredFrom! OccurredUntil(occurredAtUntil time.Time) CompletedFilterItemBuilderWithOccurredUntil // WithSequenceNumberHigherThan sets the sequence number boundary (exclusive) for the whole Filter. // This makes time boundaries unavailable (mutually exclusive). WithSequenceNumberHigherThan(sequenceNumber uint) CompletedFilterItemBuilderWithSequenceNumber // OrMatching finalizes the current FilterItem and starts a new one. OrMatching() EmptyFilterItemBuilder // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
FilterItemBuilderLackingEventTypes represents a FilterItem with predicates but no event types yet. You can optionally add event types, set time boundaries, add more items, or finalize the filter.
type FilterItemBuilderLackingPredicates ¶
type FilterItemBuilderLackingPredicates interface { // AndAnyPredicateOf adds one or multiple FilterPredicate(s) to the current FilterItem expecting ANY predicate to match. // // It sanitizes the input: // - removing empty/partial FilterPredicate(s) (key or val is "") // - sorting the FilterPredicate(s) // - removing duplicate FilterPredicate(s) AndAnyPredicateOf(predicate FilterPredicate, predicates ...FilterPredicate) CompletedFilterItemBuilder // AndAllPredicatesOf adds one or multiple FilterPredicate(s) to the current FilterItem expecting ALL predicates to match. // // It sanitizes the input: // - removing empty/partial FilterPredicate(s) (key or val is "") // - sorting the FilterPredicate(s) // - removing duplicate FilterPredicate(s) AndAllPredicatesOf(predicate FilterPredicate, predicates ...FilterPredicate) CompletedFilterItemBuilder // OccurredFrom sets the lower boundary for occurredAt (including this timestamp) for the whole Filter. OccurredFrom(occurredAtFrom time.Time) CompletedFilterItemBuilderWithOccurredFrom // OccurredUntil sets the upper boundary for occurredAt (including this timestamp) for the whole Filter. // // Currently, there is NO check if OccurredUntil is later than OccurredFrom! OccurredUntil(occurredAtUntil time.Time) CompletedFilterItemBuilderWithOccurredUntil // WithSequenceNumberHigherThan sets the sequence number boundary (exclusive) for the whole Filter. // This makes time boundaries unavailable (mutually exclusive). WithSequenceNumberHigherThan(sequenceNumber uint) CompletedFilterItemBuilderWithSequenceNumber // OrMatching finalizes the current FilterItem and starts a new one. OrMatching() EmptyFilterItemBuilder // Finalize returns the Filter once it has at least one FilterItem with at least one EventType OR one Predicate. Finalize() Filter }
FilterItemBuilderLackingPredicates represents a FilterItem with event types but no predicates yet. You can optionally add predicates, set time boundaries, add more items, or finalize the filter.
type FilterKeyString ¶
type FilterKeyString = string
FilterKeyString represents a JSON key used in filter predicate matching.
type FilterPredicate ¶
type FilterPredicate struct {
// contains filtered or unexported fields
}
FilterPredicate represents a key-value pair for matching JSON payload fields.
func P ¶
func P(key FilterKeyString, val FilterValString) FilterPredicate
P creates a new FilterPredicate with the specified key and value.
func (FilterPredicate) Key ¶
func (fp FilterPredicate) Key() FilterKeyString
Key returns the JSON key for this predicate.
func (FilterPredicate) Val ¶
func (fp FilterPredicate) Val() FilterValString
Val returns the JSON value for this predicate.
type FilterValString ¶
type FilterValString = string
FilterValString represents a JSON value used in filter predicate matching.
type Logger ¶
type Logger interface { Debug(msg string, args ...any) Info(msg string, args ...any) Warn(msg string, args ...any) Error(msg string, args ...any) }
Logger interface for SQL query logging, operational metricsCollector, warnings, and error reporting.
type MaxSequenceNumberUint ¶
type MaxSequenceNumberUint = uint
MaxSequenceNumberUint is a type alias for uint, representing the maximum sequence number for a "dynamic event stream".
type MetricsCollector ¶
type MetricsCollector interface { RecordDuration(metric string, duration time.Duration, labels map[string]string) IncrementCounter(metric string, labels map[string]string) RecordValue(metric string, value float64, labels map[string]string) }
MetricsCollector interface for collecting EventStore performance and operational metricsCollector.
type SequenceFilteringCapable ¶
type SequenceFilteringCapable interface { // WithSequenceNumberHigherThan sets the sequence number boundary (exclusive) for the reopened Filter. WithSequenceNumberHigherThan(sequenceNumber uint) CompletedFilterItemBuilderWithSequenceNumber }
SequenceFilteringCapable represents a filter state that can accept sequence number filtering. This interface provides compile-time safety - you can only call WithSequenceNumberHigherThan on filters that are compatible (no time boundaries set).
type SequenceFilteringIncompatible ¶
type SequenceFilteringIncompatible interface { // CannotAddSequenceFiltering documents why sequence filtering is not possible on this filter. CannotAddSequenceFiltering() string }
SequenceFilteringIncompatible represents a filter state that cannot accept sequence number filtering. This interface provides compile-time safety - attempting to call WithSequenceNumberHigherThan will result in a compile-time error.
type Snapshot ¶
type Snapshot struct { ProjectionType string // Type of projection (e.g., "BooksInCirculation") FilterHash string // Hash of the filter used to create this snapshot SequenceNumber MaxSequenceNumberUint // Last processed event sequence number Data json.RawMessage // Serialized projection state as JSON CreatedAt time.Time // When this snapshot was created/updated }
Snapshot represents a stored projection state with metadata for incremental updates. It contains the serialized projection data along with the sequence number of the last processed event, enabling efficient incremental updates.
func BuildSnapshot ¶
func BuildSnapshot( projectionType string, filterHash string, sequenceNumber MaxSequenceNumberUint, data json.RawMessage, ) (Snapshot, error)
BuildSnapshot creates a new Snapshot with validation.
type SpanContext ¶
SpanContext represents an active tracing span that can be finished and updated with attributes.
type StorableEvent ¶
type StorableEvent struct { EventType string OccurredAt time.Time PayloadJSON []byte MetadataJSON []byte }
StorableEvent is a DTO (data transfer object) used by the EventStore to append events and query them back.
It is built on scalars to be completely agnostic of the implementation of Domain Events in the client code.
While its properties are exported, it should only be constructed with the supplied factory methods:
- BuildStorableEvent
- BuildStorableEventWithEmptyMetadata
func BuildStorableEvent ¶
func BuildStorableEvent(eventType string, occurredAt time.Time, payloadJSON []byte, metadataJSON []byte) (StorableEvent, error)
BuildStorableEvent is a factory method for StorableEvent.
It populates the StorableEvent with the given scalar input. Returns an error if payloadJSON or metadataJSON are not valid JSON.
func BuildStorableEventWithEmptyMetadata ¶
func BuildStorableEventWithEmptyMetadata(eventType string, occurredAt time.Time, payloadJSON []byte) (StorableEvent, error)
BuildStorableEventWithEmptyMetadata is a factory method for StorableEvent.
It populates the StorableEvent with the given scalar input and creates valid empty JSON for MetadataJSON. Returns an error if payloadJSON is not valid JSON.
type StorableEvents ¶
type StorableEvents = []StorableEvent
StorableEvents is an alias type for a slice of StorableEvent.
type TracingCollector ¶
type TracingCollector interface { StartSpan(ctx context.Context, name string, attrs map[string]string) (context.Context, SpanContext) FinishSpan(spanCtx SpanContext, status string, attrs map[string]string) }
TracingCollector interface for collecting distributed tracing information from EventStore operations. This interface follows the same dependency-free pattern as MetricsCollector, allowing users to integrate with any tracing backend (OpenTelemetry, Jaeger, Zipkin, etc.) by implementing this interface.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
Package oteladapters provides OpenTelemetry adapters for the eventstore observability interfaces.
|
Package oteladapters provides OpenTelemetry adapters for the eventstore observability interfaces. |
Package postgresengine provides a PostgreSQL implementation of the eventstore interface.
|
Package postgresengine provides a PostgreSQL implementation of the eventstore interface. |
internal/adapters
Package adapters provide database adapter implementations for the PostgreSQL event store.
|
Package adapters provide database adapter implementations for the PostgreSQL event store. |