contracts

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package contracts provides the local typed contract registry used by GOWDK runtime roles.

Index

Constants

This section is empty.

Variables

View Source
var ErrEventSourceClosed = errors.New("event source closed")

ErrEventSourceClosed tells RunEventWorker that the source drained cleanly.

Functions

func ContractName

func ContractName[T any]() string

ContractName returns the stable contract name used by registry metadata and event envelopes for T.

func DispatchCommandEvents

func DispatchCommandEvents(ctx context.Context, sink CommandEventSink, registry *Registry, role Role, events []EventEnvelope) error

DispatchCommandEvents sends captured command events to sink. A nil sink uses the default in-process subscriber dispatch path.

func EmitDomain

func EmitDomain[E any](ctx context.Context, event E) error

EmitDomain records a backend-owned domain event for dispatch after the current command succeeds.

func EmitIntegration

func EmitIntegration[E any](ctx context.Context, event E) error

EmitIntegration records a durable integration event for dispatch after the current command succeeds.

func EmitPresentation

func EmitPresentation[E any](ctx context.Context, event E) error

EmitPresentation records a browser-facing presentation event for dispatch after the current command succeeds.

func ExecuteCommand

func ExecuteCommand[C, R any](ctx context.Context, registry *Registry, command C) (R, error)

ExecuteCommand runs a command and dispatches events recorded with Emit* only after the command handler succeeds.

func ExecuteCommandForRole

func ExecuteCommandForRole[C, R any](ctx context.Context, registry *Registry, role Role, command C) (R, error)

ExecuteCommandForRole runs a command owner for role and dispatches only matching event subscribers after the command succeeds.

func ExecuteCommandToBroker

func ExecuteCommandToBroker[C, R any](ctx context.Context, registry *Registry, broker Broker, command C) (R, error)

ExecuteCommandToBroker runs a command and publishes emitted events to broker after the command handler succeeds. Subscribers are not dispatched.

func ExecuteCommandToBrokerForRole

func ExecuteCommandToBrokerForRole[C, R any](ctx context.Context, registry *Registry, broker Broker, role Role, command C) (R, error)

ExecuteCommandToBrokerForRole runs a command for role and publishes emitted events to broker after the command handler succeeds.

func ExecuteCommandToOutbox

func ExecuteCommandToOutbox[C, R any](ctx context.Context, registry *Registry, outbox Outbox, command C) (R, error)

ExecuteCommandToOutbox runs a command and stores emitted events in outbox after the command handler succeeds. Subscribers are not dispatched.

func ExecuteCommandToOutboxForRole

func ExecuteCommandToOutboxForRole[C, R any](ctx context.Context, registry *Registry, outbox Outbox, role Role, command C) (R, error)

ExecuteCommandToOutboxForRole runs a command for role and stores emitted events in outbox after the command handler succeeds.

func ExecuteCommandToPresentationFanout

func ExecuteCommandToPresentationFanout[C, R any](ctx context.Context, registry *Registry, fanout PresentationFanout, command C) (R, error)

ExecuteCommandToPresentationFanout runs a command and sends presentation events to fanout after the command handler succeeds. Subscribers are not dispatched and non-presentation events are not sent to fanout.

func ExecuteCommandToPresentationFanoutForRole

func ExecuteCommandToPresentationFanoutForRole[C, R any](ctx context.Context, registry *Registry, fanout PresentationFanout, role Role, command C) (R, error)

ExecuteCommandToPresentationFanoutForRole runs a command for role and sends presentation events to fanout after the command handler succeeds.

func ExecuteJob

func ExecuteJob[J any](ctx context.Context, registry *Registry, job J) error

ExecuteJob runs a registered job handler.

func ExecuteJobForRole

func ExecuteJobForRole[J any](ctx context.Context, registry *Registry, role Role, job J) error

ExecuteJobForRole runs a job handler only when it is available to role.

func ExecuteQuery

func ExecuteQuery[Q, R any](ctx context.Context, registry *Registry, query Q) (R, error)

ExecuteQuery runs a registered query handler.

func ExecuteQueryForRole

func ExecuteQueryForRole[Q, R any](ctx context.Context, registry *Registry, role Role, query Q) (R, error)

ExecuteQueryForRole runs a query handler only when it is available to role.

func Is

func Is(err error, kind ErrorKind) bool

Is reports whether err or one of its causes is a contract Error with kind.

func PublishDomain

func PublishDomain[E any](ctx context.Context, registry *Registry, event E) error

PublishDomain dispatches a domain event immediately.

func PublishDomainForRole

func PublishDomainForRole[E any](ctx context.Context, registry *Registry, role Role, event E) error

PublishDomainForRole dispatches a domain event to subscribers available to role.

func PublishEnvelope

func PublishEnvelope(ctx context.Context, registry *Registry, event EventEnvelope) error

PublishEnvelope dispatches one captured event envelope immediately.

func PublishEnvelopeForRole

func PublishEnvelopeForRole(ctx context.Context, registry *Registry, role Role, event EventEnvelope) error

PublishEnvelopeForRole dispatches one captured event envelope to subscribers available to role.

func PublishEnvelopes

func PublishEnvelopes(ctx context.Context, registry *Registry, events []EventEnvelope) error

PublishEnvelopes dispatches captured event envelopes in order.

func PublishEnvelopesForRole

func PublishEnvelopesForRole(ctx context.Context, registry *Registry, role Role, events []EventEnvelope) error

PublishEnvelopesForRole dispatches captured event envelopes in order to subscribers available to role.

func PublishEventsToBroker

func PublishEventsToBroker(ctx context.Context, broker Broker, events []EventEnvelope) error

PublishEventsToBroker sends captured events to broker in one ordered batch.

func PublishIntegration

func PublishIntegration[E any](ctx context.Context, registry *Registry, event E) error

PublishIntegration dispatches an integration event immediately.

func PublishIntegrationForRole

func PublishIntegrationForRole[E any](ctx context.Context, registry *Registry, role Role, event E) error

PublishIntegrationForRole dispatches an integration event to subscribers available to role.

func PublishPresentation

func PublishPresentation[E any](ctx context.Context, registry *Registry, event E) error

PublishPresentation dispatches a presentation event immediately.

func PublishPresentationForRole

func PublishPresentationForRole[E any](ctx context.Context, registry *Registry, role Role, event E) error

PublishPresentationForRole dispatches a presentation event to subscribers available to role.

func RegisterCommand

func RegisterCommand[C, R any](registry *Registry, handler CommandHandler[C, R], roles ...Role) error

RegisterCommand registers one command owner. A command can have exactly one owner handler.

func RegisterDomainEvent

func RegisterDomainEvent[E any](registry *Registry, handler EventHandler[E], roles ...Role) error

RegisterDomainEvent registers a subscriber for a backend-owned domain event.

func RegisterIntegrationEvent

func RegisterIntegrationEvent[E any](registry *Registry, handler EventHandler[E], roles ...Role) error

RegisterIntegrationEvent registers a subscriber for a durable integration event.

func RegisterJob

func RegisterJob[J any](registry *Registry, handler JobHandler[J], roles ...Role) error

RegisterJob registers one background or scheduled job handler.

func RegisterPresentationEvent

func RegisterPresentationEvent[E any](registry *Registry, handler EventHandler[E], roles ...Role) error

RegisterPresentationEvent registers a subscriber or fanout hook for a browser-facing presentation event. Presentation events are output only; they must not be treated as trusted domain input.

func RegisterQuery

func RegisterQuery[Q, R any](registry *Registry, handler QueryHandler[Q, R], roles ...Role) error

RegisterQuery registers one readonly query handler.

func RunEventWorker

func RunEventWorker(ctx context.Context, registry *Registry, source EventSource) error

RunEventWorker reads batches from source and dispatches them to worker-role subscribers until ctx is canceled or source returns ErrEventSourceClosed.

func RunEventWorkerForRole

func RunEventWorkerForRole(ctx context.Context, registry *Registry, role Role, source EventSource) error

RunEventWorkerForRole reads batches from source and dispatches them to subscribers available to role.

func SendPresentationEventsToFanout

func SendPresentationEventsToFanout(ctx context.Context, fanout PresentationFanout, events []EventEnvelope) error

SendPresentationEventsToFanout sends only presentation events to fanout.

Types

type Broker

type Broker interface {
	PublishEvents(context.Context, []EventEnvelope) error
}

Broker publishes command-emitted events to an external delivery system. Implementations decide serialization, acknowledgements, and delivery policy.

type CommandEventSink

type CommandEventSink interface {
	HandleCommandEvents(context.Context, *Registry, Role, []EventEnvelope) error
}

CommandEventSink receives events captured from a successful command. The registry and role let sinks choose between in-process subscriber dispatch, durable storage, broker publication, or browser-facing presentation delivery.

func BrokerCommandEventSink

func BrokerCommandEventSink(broker Broker) CommandEventSink

BrokerCommandEventSink returns a sink that publishes captured events to broker without dispatching local subscribers.

func CompositeCommandEventSink

func CompositeCommandEventSink(sinks ...CommandEventSink) CommandEventSink

CompositeCommandEventSink returns a sink that sends the same captured event batch to each sink in order. Nil sinks are ignored.

func InProcessCommandEventSink

func InProcessCommandEventSink() CommandEventSink

InProcessCommandEventSink returns a sink that dispatches captured events through the local registry with role filtering.

func OutboxCommandEventSink

func OutboxCommandEventSink(outbox Outbox) CommandEventSink

OutboxCommandEventSink returns a sink that stores captured events in outbox without dispatching local subscribers.

func PresentationFanoutCommandEventSink

func PresentationFanoutCommandEventSink(fanout PresentationFanout) CommandEventSink

PresentationFanoutCommandEventSink returns a sink that sends only presentation events to fanout.

type CommandHandler

type CommandHandler[C, R any] func(context.Context, C) (R, error)

Handler types accepted by the registry.

type Error

type Error struct {
	Kind     ErrorKind
	Contract string
	Message  string
	Cause    error
}

Error is returned for contract registry and dispatch failures.

func (Error) Error

func (err Error) Error() string

func (Error) Unwrap

func (err Error) Unwrap() error

type ErrorKind

type ErrorKind string

ErrorKind identifies contract registry or dispatch failures.

const (
	ErrDuplicateHandler   ErrorKind = "duplicate_handler"
	ErrMissingHandler     ErrorKind = "missing_handler"
	ErrUnsupportedHandler ErrorKind = "unsupported_handler"
	ErrNilHandler         ErrorKind = "nil_handler"
	ErrNoEventRecorder    ErrorKind = "no_event_recorder"
	ErrSubscriberFailed   ErrorKind = "subscriber_failed"
	ErrRoleNotAllowed     ErrorKind = "role_not_allowed"
)

type EventBatch

type EventBatch struct {
	Events []EventEnvelope
	Ack    func(context.Context) error
	Nack   func(context.Context, error) error
}

EventBatch is one ordered delivery batch from an outbox, queue, or broker adapter. Ack and Nack are optional adapter hooks.

type EventCategory

type EventCategory string

EventCategory identifies the trust boundary for an event.

const (
	DomainEvent       EventCategory = "domain"
	IntegrationEvent  EventCategory = "integration"
	PresentationEvent EventCategory = "presentation"
)

type EventEnvelope

type EventEnvelope struct {
	Category EventCategory
	Type     string
	Value    any
}

EventEnvelope is a backend-owned event captured from a successful command.

func CaptureCommandEvents

func CaptureCommandEvents[C, R any](ctx context.Context, registry *Registry, command C) (R, []EventEnvelope, error)

CaptureCommandEvents runs a command and returns events recorded with Emit* after the command handler succeeds. Subscribers are not dispatched.

func CaptureCommandEventsForRole

func CaptureCommandEventsForRole[C, R any](ctx context.Context, registry *Registry, role Role, command C) (R, []EventEnvelope, error)

CaptureCommandEventsForRole runs a command for role and captures emitted events without dispatching subscribers.

func (EventEnvelope) Observation

func (event EventEnvelope) Observation(name ObservationName) Observation

Observation returns a named observation for this captured event envelope.

func (EventEnvelope) ObservationForRole

func (event EventEnvelope) ObservationForRole(name ObservationName, role Role) Observation

ObservationForRole returns a named observation for this captured event envelope and records the runtime role performing the operation.

func (EventEnvelope) ObservationLabels

func (event EventEnvelope) ObservationLabels() ObservationLabels

ObservationLabels returns stable labels for this captured event envelope.

type EventHandler

type EventHandler[E any] func(context.Context, E) error

Handler types accepted by the registry.

type EventSource

type EventSource interface {
	ReceiveEventBatch(context.Context) (EventBatch, error)
}

EventSource receives event batches for a worker role.

type JobHandler

type JobHandler[J any] func(context.Context, J) error

Handler types accepted by the registry.

type Kind

type Kind string

Kind identifies a registered contract type.

const (
	Query   Kind = "query"
	Command Kind = "command"
	Event   Kind = "event"
	Job     Kind = "job"
)

type Metadata

type Metadata struct {
	Kind          Kind
	EventCategory EventCategory
	Type          string
	Result        string
	Handlers      int
	Roles         []Role
}

Metadata describes one registered contract.

func (Metadata) Observation

func (metadata Metadata) Observation(name ObservationName) Observation

Observation returns a named observation for this registered contract.

func (Metadata) ObservationForRole

func (metadata Metadata) ObservationForRole(name ObservationName, role Role) Observation

ObservationForRole returns a named observation for this registered contract and records the runtime role performing the operation.

func (Metadata) ObservationLabels

func (metadata Metadata) ObservationLabels() ObservationLabels

ObservationLabels returns stable labels for this registered contract.

type Observation

type Observation struct {
	Name   ObservationName
	Labels ObservationLabels
}

Observation combines a stable operation name with stable contract labels.

func NewObservation

func NewObservation(name ObservationName, labels ObservationLabels) Observation

NewObservation creates an observation and copies slice labels so callers can safely reuse or mutate their input values.

type ObservationLabels

type ObservationLabels struct {
	Kind          Kind
	EventCategory EventCategory
	Contract      string
	Result        string
	Role          Role
	Roles         []Role
	Handlers      int
}

ObservationLabels are stable contract attributes for logs, metrics, and traces. Empty fields are intentionally omitted by callers that do not need them.

type ObservationName

type ObservationName string

ObservationName is a stable operation name for contract logs, metrics, and traces. These names are intentionally independent from CLI display text.

const (
	ObservationRegisterQuery           ObservationName = "gowdk.contract.register.query"
	ObservationRegisterCommand         ObservationName = "gowdk.contract.register.command"
	ObservationRegisterEvent           ObservationName = "gowdk.contract.register.event"
	ObservationRegisterJob             ObservationName = "gowdk.contract.register.job"
	ObservationExecuteQuery            ObservationName = "gowdk.contract.execute.query"
	ObservationExecuteCommand          ObservationName = "gowdk.contract.execute.command"
	ObservationCaptureCommand          ObservationName = "gowdk.contract.capture.command"
	ObservationExecuteJob              ObservationName = "gowdk.contract.execute.job"
	ObservationPublishEvent            ObservationName = "gowdk.contract.publish.event"
	ObservationStoreCommandEvents      ObservationName = "gowdk.contract.outbox.store"
	ObservationPublishBrokerEvents     ObservationName = "gowdk.contract.broker.publish"
	ObservationSendPresentationEvents  ObservationName = "gowdk.contract.presentation.send"
	ObservationWorkerReceiveEventBatch ObservationName = "gowdk.contract.worker.receive"
	ObservationWorkerAckEventBatch     ObservationName = "gowdk.contract.worker.ack"
	ObservationWorkerNackEventBatch    ObservationName = "gowdk.contract.worker.nack"
)

type Outbox

type Outbox interface {
	StoreEvents(context.Context, []EventEnvelope) error
}

Outbox stores command-emitted events for durable delivery. Implementations decide persistence, transactions, retries, and broker publication.

type PresentationFanout

type PresentationFanout interface {
	SendPresentationEvents(context.Context, []EventEnvelope) error
}

PresentationFanout sends browser-facing presentation events to a realtime transport such as SSE or WebSocket.

type QueryHandler

type QueryHandler[Q, R any] func(context.Context, Q) (R, error)

Handler types accepted by the registry.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry stores typed contract handlers for one runtime.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty contract registry.

func (*Registry) Contracts

func (registry *Registry) Contracts() []Metadata

Contracts returns deterministic metadata for registered contracts.

func (*Registry) ContractsForRole

func (registry *Registry) ContractsForRole(role Role) []Metadata

ContractsForRole returns deterministic metadata for contracts available to role.

type Role

type Role string

Role identifies a runtime role that can execute a contract.

const (
	RoleWeb    Role = "web"
	RoleWorker Role = "worker"
	RoleCron   Role = "cron"
	RoleAPI    Role = "api"
	RoleAdmin  Role = "admin"
)

Directories

Path Synopsis
Package fileoutbox provides a dependency-free JSON Lines outbox adapter for runtime/contracts.
Package fileoutbox provides a dependency-free JSON Lines outbox adapter for runtime/contracts.
Package membroker provides an in-memory broker adapter for runtime/contracts.
Package membroker provides an in-memory broker adapter for runtime/contracts.
Package natsbroker provides a NATS adapter for runtime/contracts.
Package natsbroker provides a NATS adapter for runtime/contracts.
Package redisstream provides a Redis Streams adapter for runtime/contracts.
Package redisstream provides a Redis Streams adapter for runtime/contracts.
Package sse provides a dependency-free server-sent events presentation fanout adapter for runtime/contracts.
Package sse provides a dependency-free server-sent events presentation fanout adapter for runtime/contracts.
Package websocketfanout provides a WebSocket presentation fanout adapter for runtime/contracts.
Package websocketfanout provides a WebSocket presentation fanout adapter for runtime/contracts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL