Documentation
¶
Overview ¶
Package event defines the CloudEvents 1.0 envelope and the types a domain uses to raise its events.
The package exports:
- SpecVersion, the CloudEvents version it implements, and Event, one event's context attributes and data, with Event.Validate, which reports every way an event breaks the specification
- Header, a message's headers, and Encode and Decode, which map an Event to and from binary content mode
- EventKind, one event a domain raises, its type paired with the Go type of its data; Define, which declares one, and CheckType, the rule its type follows; EventKind.Type, and EventKind.Raise, which adds an event of the kind to a Queue
- Queue, the events one command raises, with Queue.Events, a copy of them, and Queue.Err, every failure a raise held
- Sink, what writes stamped events into a transaction, and Recorder, which emits a command's events through one, with NewRecorder, which returns one, and Recorder.Emit, which wraps a command's body into the function a transaction runs
- Option, which configures a Recorder, with Clock, the time it stamps, and IDs, how it mints an event id
- Permanent, which marks a handler's error as one redelivery cannot fix, and IsPermanent, which reports the mark
Envelope ¶
An Event carries the context attributes a service sets, and Encode and Decode map it to and from binary content mode: each attribute is a ce-prefixed header, datacontenttype is the content-type header, and the data travels as the message body. Header is a plain map, so it converts to a NATS or HTTP header without this package importing either.
Raising and emitting ¶
A domain raises events, and a recorder emits them. A domain declares each event it raises as an EventKind, which pairs the event type with the Go type of its data:
var Started = event.Define[StartedData]("exercise.started")
A command raises its events into a Queue while it runs, and a Recorder emits them through its Sink into the command's own transaction, so an event is emitted only in the transaction of the command that makes it true. Recorder.Emit states when it stamps and writes.
The transaction is a type parameter, so this package names no database. The composition root fixes the type when it builds the recorder over a sink, such as an outbox's, and passing a pool where the sink expects its transaction type fails to compile.
Handling ¶
A handler that must never see an event again wraps its error with Permanent.
The package uses the standard library alone.
Index ¶
Constants ¶
const SpecVersion = "1.0"
SpecVersion is the CloudEvents specification version this package implements.
Variables ¶
This section is empty.
Functions ¶
func CheckType ¶
CheckType reports whether t is an event type a broker can route: one or more tokens separated by '.', none of them empty, with no whitespace, '*', or '>'. The rule is a subject's, so a provider can route on the type itself, and it admits the reverse-DNS types CloudEvents recommends, such as "lab.grant.approved".
func IsPermanent ¶
IsPermanent reports whether any error in err's tree was marked by Permanent.
Types ¶
type Event ¶
type Event struct {
ID string
Source string
Type string
Subject string
DataContentType string
DataSchema string
Time time.Time
Data []byte
Extensions map[string]string
}
Event is one CloudEvents 1.0 event. ID, Source, and Type are required; the specversion is always SpecVersion and is not a field. A zero Time and an empty Subject, DataContentType, or DataSchema are absent attributes. Extensions holds the extension attributes, such as traceparent, keyed by name.
func Decode ¶
Decode reads an event from binary content mode. Header names match case-insensitively, so a canonicalized HTTP header decodes too, and a lowercase name wins over another spelling of it. Any ce-prefixed header that is not a context attribute is an extension. The time attribute is parsed as RFC 3339 and returned in UTC, whatever offset it was written with. The result must carry specversion 1.0 and pass Event.Validate.
type EventKind ¶
type EventKind[T any] struct { // contains filtered or unexported fields }
EventKind is one event a domain raises: its type, and T, the Go type of its data. A domain declares its kinds with Define, so the type and T cannot drift apart at a call site.
func Define ¶
Define declares the event kind of type typ, whose data is a T encoded as JSON. A type that breaks CheckType is a declaration defect, so Define panics; when the kind is a package variable, it panics at the package's initialization.
type Header ¶
Header is a message's headers in binary content mode. Its shape matches nats.Header and http.Header. Values are written as given: a provider whose protocol binding requires encoding them, such as HTTP's percent-encoding, encodes them itself.
type Option ¶
type Option func(*options)
Option configures a Recorder.
type Queue ¶
type Queue struct {
// contains filtered or unexported fields
}
Queue holds the events one command raises, in the order it raises them. Recorder.Emit gives each run of a command a fresh queue and emits it when the command succeeds; a command never emits a queue itself.
type Recorder ¶
type Recorder[Tx any] struct { // contains filtered or unexported fields }
Recorder emits the events a command raises into the command's transaction, stamped with the id, source, and time the domain never sets. The composition root builds one per service and injects it into each domain.
func NewRecorder ¶
NewRecorder builds the recorder that writes through sink and stamps every event with source, the service's own URI-reference. Source is one value for the whole service, never a replica's, because a consumer deduplicates on the source and id together. A nil sink or an empty source is a wiring defect and panics.
func (*Recorder[Tx]) Emit ¶
func (r *Recorder[Tx]) Emit[R any](ctx context.Context, fn func(Tx, *Queue) (R, error)) func(Tx) (R, error)
Emit wraps fn, a command's body, into the function a transaction runs, such as sqlate's Transact. The body runs on the transaction with a fresh Queue. When it returns an error, Emit returns it and writes nothing. When it succeeds, Emit stamps each queued event, its time the clock's in UTC, and writes them, in the order raised, through the sink into the same transaction, before the caller commits. A failed raise or write fails the command, so the transaction rolls back with its state and its events together. Emit neither begins nor ends the transaction; the code that began it ends it. ctx is the context of the write.