Documentation ¶
Index ¶
- Constants
- func ApplyWith[Data any](r Registerer, handler func(Of[Data]), eventNames ...string)
- func CompareSorting[A, B any](s Sorting, a Of[A], b Of[B]) (cmp int8)
- func Equal(events ...Of[any]) bool
- func Filter[D any](events <-chan Of[D], queries ...Query) <-chan Of[D]
- func HandleWith[Data any](r Registerer, handler func(Of[Data]), eventNames ...string)
- func Must[D any](events <-chan Of[D], errs <-chan error, err error) (<-chan Of[D], <-chan error)
- func NewRegistry(opts ...codec.Option) *codec.Registry
- func RegisterHandler[Data any](r Registerer, eventName string, handler func(Of[Data]))
- func Sort[Events ~[]Of[D], D any](events Events, sort Sorting, dir SortDirection) Events
- func SortMulti[Events ~[]Of[D], D any](events Events, sorts ...SortOptions) Events
- func Test[Data any](q Query, evt Of[Data]) bool
- type AggregateRef
- type Bus
- type Data
- type Event
- type Evt
- type Handlers
- type Of
- type Option
- type Publisher
- type Query
- type Registerer
- type SortDirection
- type SortOptions
- type Sorting
- type Store
- type Subscriber
Constants ¶
const ( // SortTime is a Sorting option that sorts events by their timestamp, with // earlier events coming before later events. SortTime = Sorting(iota) // SortAggregateName is a Sorting value that sorts events by their aggregate // name in a Query. Events with the same aggregate name are considered equal // when sorting with this value. SortAggregateName // SortAggregateID is a Sorting option that sorts events based on the // lexicographical order of their aggregate ID. SortAggregateID // SortAggregateVersion is a Sorting option that sorts events based on their // aggregate version, with lower versions coming first. SortAggregateVersion )
#region sortings
const ( // SortAsc is a SortDirection constant that represents sorting in ascending // order. Use it with Sorting and SortOptions to specify the desired sort // direction when querying events from an event store. SortAsc = SortDirection(iota) // SortDesc is a SortDirection that indicates the order of sorting should be in // descending order when comparing values. SortDesc )
const All = "*"
All is a special event name that matches all events.
Variables ¶
This section is empty.
Functions ¶
func ApplyWith ¶ added in v0.1.2
func ApplyWith[Data any](r Registerer, handler func(Of[Data]), eventNames ...string)
ApplyWith is an alias for RegisterHandler. Use ApplyWith instead of RegisterHandler to make code more concise:
type Foo struct { *projection.Base Foo string } func NewFoo() *Foo { foo := &Foo{Base: projection.New()} // Because we "apply" events to the projection. event.ApplyWith(foo, foo.applyFoo, "foo") return foo } func (f *Foo) applyFoo(e event.Of[string]) { f.Foo = e.Data() }
func CompareSorting ¶ added in v0.1.2
CompareSorting compares two events a and b using the specified Sorting s. It returns -1 if a is less than b, 0 if they are equal, or 1 if a is greater than b. The comparison is based on the time, aggregate name, aggregate ID, or aggregate version, depending on the provided Sorting s.
func Equal ¶
Equal returns true if all provided events have the same ID, name, time, data, and aggregate information. It returns false otherwise. If less than two events are provided, it returns true.
func Filter ¶
Filter filters the events from the given input channel based on the provided queries and returns a new channel with only the events that pass all the queries. If no queries are provided, the input channel is returned unchanged.
func HandleWith ¶ added in v0.1.2
func HandleWith[Data any](r Registerer, handler func(Of[Data]), eventNames ...string)
HandleWith is an alias for RegisterHandler. Use HandleWith instead of RegisterHandler to make code more concise:
import "github.com/modernice/goes/event/handler" var bus event.Bus h := handler.New(bus) event.HandleWith(h, h.handleFoo, "foo")
func Must ¶
Must wraps the given event and error channels, and panics if the provided error is not nil. It returns the same event and error channels if the error is nil. This function can be used to simplify error handling when setting up event subscriptions, ensuring that a valid subscription is established before proceeding.
Example ¶
events := event.Must(bus.Subscribe(ctx, "event-name"))
func NewRegistry ¶ added in v0.1.2
NewRegistry returns a new event registry for encoding and decoding of event data for transmission over a network.
func RegisterHandler ¶ added in v0.1.2
func RegisterHandler[Data any](r Registerer, eventName string, handler func(Of[Data]))
RegisterHandler registers the handler for the given event.
Example using *aggregate.Base:
type Foo struct { *aggregate.Base Foo string Bar int Baz bool } type FooEvent { Foo string } type BazEvent { Baz bool } func NewFoo(id uuid.UUID) *Foo { foo := &Foo{Base: aggregate.New("foo", id)} event.RegisterHandler(foo, "foo", foo.applyFoo) event.RegisterHandler(foo, "bar", foo.applyBar) event.RegisterHandler(foo, "baz", foo.applyBaz) return foo } func (f *Foo) applyFoo(e event.Of[FooEvent]) { f.Foo = e.Data().Foo } func (f *Foo) applyBar(e event.Of[int]) { f.Bar = e.Data() } func (f *Foo) applyBaz(e event.Of[BazEvent]) { f.Baz = e.Data().Baz }
func Sort ¶
func Sort[Events ~[]Of[D], D any](events Events, sort Sorting, dir SortDirection) Events
Sort sorts the provided events according to the specified Sorting and SortDirection, returning a new slice of sorted events.
func SortMulti ¶
func SortMulti[Events ~[]Of[D], D any](events Events, sorts ...SortOptions) Events
SortMulti sorts a slice of events based on the provided sort options, in the order they appear. If multiple events have the same value for a specified sort option, they will be sorted based on the next sort option in the list. If all sort options are equal, the original order is preserved.
Types ¶
type AggregateRef ¶
AggregateRef represents a reference to an aggregate with a specific Name and ID. It provides methods to check if it's a zero value, retrieve aggregate information, split the Name and ID, and parse a string into an AggregateRef.
func (AggregateRef) Aggregate ¶ added in v0.1.2
func (ref AggregateRef) Aggregate() (uuid.UUID, string, int)
Aggregate returns the ID, name, and version of the AggregateRef. The returned version is always -1 as AggregateRef does not store version information.
func (AggregateRef) IsZero ¶ added in v0.1.2
func (ref AggregateRef) IsZero() bool
IsZero reports whether the AggregateRef is a zero value, meaning it has an empty Name and a zero UUID.
func (*AggregateRef) Parse ¶ added in v0.1.2
func (ref *AggregateRef) Parse(v string) error
Parse parses the given string representation of an AggregateRef and sets the Name and ID fields of the receiver. The input string should be in the format "Name(ID)" where Name is a non-empty string and ID is a valid UUID. Returns an error if the input string is invalid or cannot be parsed.
func (AggregateRef) Split ¶ added in v0.1.2
func (ref AggregateRef) Split() (uuid.UUID, string)
Split returns the ID and Name of the AggregateRef.
func (AggregateRef) String ¶ added in v0.1.2
func (ref AggregateRef) String() string
String returns a string representation of the AggregateRef in the format "Name(UUID)".
type Bus ¶
type Bus interface { Publisher Subscriber }
#region bus Bus combines the capabilities of both a Publisher and a Subscriber, allowing it to send events to all subscribers and set up subscriptions for specific event names. It is an interface that embeds the Publisher and Subscriber interfaces.
type Data ¶
type Data[D any] struct { ID uuid.UUID Name string Time time.Time Data D AggregateName string AggregateID uuid.UUID AggregateVersion int }
Data is a struct that holds event information such as its unique ID, name, time, and arbitrary data. Additionally, it contains aggregate-related fields like AggregateName, AggregateID, and AggregateVersion.
type Evt ¶ added in v0.1.2
Evt is a concrete implementation of the Of interface, representing an event with specific data type and associated metadata such as the event's ID, name, time, and aggregate information. Evt can be used to create, manipulate, and test events in a type-safe manner.
func Any ¶ added in v0.1.2
Any returns an Evt[any] that is a copy of the given Of[Data] event with its data type erased. This can be useful when working with heterogeneous event lists where the specific data type is not important.
func Cast ¶ added in v0.1.2
Cast converts an event with data of type From to an event with data of type To. The new event has the same ID, name, time, and aggregate information as the original event, but the data is cast to the specified To type.
func Expand ¶ added in v0.1.2
Expand converts an Of[Data] event into an Evt[Data] event, preserving the event's properties. If the input event is already of type Evt[Data], it is returned directly. Otherwise, a new Evt[Data] event is created with the same properties as the input event.
func New ¶
New creates a new event with the specified name and data, applying any provided options such as ID, Time, or Aggregate information. It returns an Evt struct containing the event data and metadata.
func TryCast ¶ added in v0.1.2
TryCast attempts to cast an event with data of type From to an event with data of type To. It returns the casted event and a boolean value indicating whether the casting was successful or not.
func (Evt[D]) Aggregate ¶ added in v0.1.2
Aggregate returns the id, name, and version of the aggregate that the event belongs to. If the event is not an aggregate event, it returns zero values.
func (Evt[D]) Any ¶ added in v0.1.2
Any converts an event with a specific data type (Of[Data]) to an event with the generic any data type (Evt[any]).
func (Evt[D]) Data ¶ added in v0.1.2
func (evt Evt[D]) Data() D
Data returns the event data of the Evt.
func (Evt[D]) Event ¶ added in v0.1.2
Event returns the unique id, name, user-provided event data, and the time at which the event was raised. If the Aggregate method of an event returns non-zero values, the event is considered to belong to the event stream of that aggregate.
type Handlers ¶ added in v0.2.1
Handlers is a map of event names to event handlers. Handlers can be embedded into structs to implement Registerer. *github.com/modernice/goes/aggregate.Base embeds Handlers to allow for convenient registration of event handlers.
func (Handlers) EventHandlers ¶ added in v0.2.1
EventHandlers returns the handlers for the given event.
func (Handlers) HandleEvent ¶ added in v0.2.1
HandleEvent calls each registered handler of the given Event.
func (Handlers) RegisterEventHandler ¶ added in v0.2.1
RegisterEventHandler implements Registerer.
type Of ¶ added in v0.1.2
type Of[Data any] interface { // ID returns the id of the event. ID() uuid.UUID // Name returns the name of the event. Name() string // Time returns the time of the event. Time() time.Time // Data returns the event data. Data() Data // Aggregate returns the id, name and version of the aggregate that the // event belongs to. aggregate should return zero values if the event is not // an aggregate event. Aggregate() (id uuid.UUID, name string, version int) }
Of is an event with the given specific data type. An event has a unique id, a name, user-provided event data, and the time at which the event was raised.
If the Aggregate method of an event returns non-zero values, the event is considered to belong to the event stream of that aggregate:
var evt event.Event id, name, version := evt.Aggregate() // id is the UUID of the aggregate that the event belongs to // name is the name of the aggregate that the event belongs to // version is the optimistic concurrency version of the event within the // event stream of the aggregate
If an event is not part of an aggregate, the Aggregate method should return only zero values.
Use the New function to create an event:
evt := event.New("foo", 3) // evt.Name() == "foo" // evt.Data() == 3 // evt.Time() == time.Now()
To create an event for an aggregate, use the Aggregate() option:
var aggregateID uuid.UUID var aggregateName string var aggregateVersion int evt := event.New("foo", 3, event.Aggregate(aggregateID, aggregateName, aggregateVersion))
type Option ¶
func Aggregate ¶
Aggregate returns the id, name, and version of the aggregate that the event belongs to. If the event is not an aggregate event, it should return zero values.
type Publisher ¶ added in v0.1.2
type Publisher interface { // Publish sends the given events to all subscribers of the event bus. It takes // a context and a variadic list of events as arguments and returns an error if // any occurred during the process. Publish(ctx context.Context, events ...Event) error }
Publisher is an interface that represents the ability to publish events to a message bus. It provides a single method, Publish, which takes a context and a variadic list of events and returns an error if the publishing process encounters any issues.
type Query ¶
type Query interface { // Names returns a slice of event names included in the Query. Names() []string // IDs returns a slice of UUIDs that the Query should match. The returned events // will have their EventID equal to one of the UUIDs in the slice. IDs() []uuid.UUID // Times returns the time constraints of the query, specifying the desired range // of event timestamps to be included in the result set. Times() time.Constraints // AggregateNames returns a slice of aggregate names that the Query is filtering // for. AggregateNames() []string // AggregateIDs returns a slice of UUIDs representing the aggregate IDs that the // Query is constrained to. AggregateIDs() []uuid.UUID // AggregateVersions returns the version constraints of the queried Aggregates // as a version.Constraints value. AggregateVersions() version.Constraints // Aggregates returns a slice of AggregateRef, representing the aggregate // references that match the query. Aggregates() []AggregateRef // Sortings returns a slice of SortOptions specifying the sorting criteria for // the query results. The events in the result set will be sorted according to // the provided sorting options in the order they appear in the slice. Sortings() []SortOptions }
#region query
Query is an interface that represents a set of criteria for filtering and sorting events when querying an event store. It provides methods to access constraints on event names, aggregate IDs, time ranges, aggregate names, aggregate versions, and custom sorting options.
type Registerer ¶ added in v0.1.2
type Registerer interface { // RegisterEventHandler registers an event handler for the given event name. RegisterEventHandler(eventName string, handler func(Event)) }
A Registerer can register handlers for different events. Types that implement Registerer can be passed to RegisterHandler(), ApplyWith(), and HandleWith() to conveniently register handlers for events.
var reg event.Registerer event.RegisterEventHandler(reg, "foo", func(e event.Of[FooEvent]) { log.Printf("handled %q event with data %v", e.Name(), e.Data()) }
ApplyWith() and HandleWith() are aliases for RegisterHandler(), to allow for more concise code.
type SortDirection ¶
type SortDirection int
SortDirection determines the order of sorting in a query. It can be either ascending (SortAsc) or descending (SortDesc).
func (SortDirection) Bool ¶
func (dir SortDirection) Bool(b bool) bool
Bool returns true if the given bool b matches the SortDirection, and false otherwise. If SortDirection is SortDesc, the result is the negation of b.
type SortOptions ¶
type SortOptions struct { Sort Sorting Dir SortDirection }
SortOptions is a configuration struct used to specify the sorting criteria and direction for event queries. It contains a Sorting field to determine the sorting attribute (such as time, aggregate name, aggregate ID, or aggregate version) and a SortDirection field to indicate the sorting order (ascending or descending).
type Sorting ¶
type Sorting int
Sorting is an enumeration of the possible ways to sort Events when querying a Store. Supported sort options include sorting by time, aggregate name, aggregate ID, and aggregate version.
type Store ¶
type Store interface { // Insert inserts the provided Events into the Store. Returns an error if any // Event could not be inserted. Insert(context.Context, ...Event) error // Find retrieves the Event with the specified UUID from the Store. It returns // an error if the Event could not be found or if there was an issue accessing // the Store. Find(context.Context, uuid.UUID) (Event, error) // Query searches for Events in the Store that match the provided Query and // returns two channels: one for the found Events and another for errors that // may occur during the search. An error is returned if the search cannot be // started. Query(context.Context, Query) (<-chan Event, <-chan error, error) // Delete removes the specified Events from the Store. It returns an error if // any of the deletions fail. Delete(context.Context, ...Event) error }
#region store
Store is an interface that provides methods for managing Event storage, including insertion, retrieval, querying, and deletion of events. Implementations should handle the storage and retrieval of events according to the provided Query constraints, such as filtering by aggregate names, IDs, and versions.
type Subscriber ¶ added in v0.1.2
type Subscriber interface { // Subscribe sets up a subscription for the specified event names, returning // channels for receiving events and errors, as well as an error if the // subscription fails. The context can be used to cancel the subscription. Subscribe(ctx context.Context, names ...string) (<-chan Event, <-chan error, error) }
Subscriber is an interface that provides a method for subscribing to specific events by their names. The Subscribe method returns a channel for receiving events, a channel for receiving errors, and an error if there are any issues during the subscription process.
Directories ¶
Path | Synopsis |
---|---|
Package query provides an event query builder.
|
Package query provides an event query builder. |
time
Package time provides time constraints for queries.
|
Package time provides time constraints for queries. |
version
Package version provides version constraints for queries.
|
Package version provides version constraints for queries. |