command

package
v0.1.0-alpha.1 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2021 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package command contains types and interfaces for implementing Command Handlers and dispatching Domain Commands, necessary for producing side effects in your Aggregates and system, and implement your Domain's business logic.

Index

Constants

View Source
const FailedType = "command-failed"

FailedType is the default stream type used by ErrorRecorder to record failed commands to the Event Store.

Variables

This section is empty.

Functions

This section is empty.

Types

type Command

type Command eventually.Payload

Command is a marker interface that represents a Domain Command.

type Dispatcher

type Dispatcher interface {
	Dispatch(context.Context, eventually.Command) error
}

Dispatcher represents a component that routes Domain Commands into their appropriate Command Handlers.

Dispatchers might be synchronous, where the Command is directly sent to the Command Handler and the business logic is executed synchronously.

Dispatchers might also be asynchronous, where the Command is send to an external queue and return from the Dispatch call immediately, while the Command Handler picks up the Command from the external queue and executes the business logic.

Make sure to pick the right kind of Command Dispatcher that suits your application needs.

type ErrorRecorder

type ErrorRecorder struct {
	Handler

	// Appender is the Event Store instance used for appending domain events.
	Appender eventstore.Appender

	// CaptureErrors specifies whether an error reported from the
	// command.Handler should be captured (or "silenced") by this component
	// and return nil instead.
	//
	// Default behavior is to return all errors from the command.Handler
	// to the caller.
	CaptureErrors bool

	// StreamType specifies the stream type used for the events produced by this component.
	// If unspecified, FailedCommandType will be used by default.
	StreamType string

	// StreamNameMapper maps to a StreamName value based on the command that failed.
	// This is useful in case you want to use the same Aggregate id the command is targeting.
	//
	// If unspecified, the command name will be used instead.
	StreamNameMapper func(cmd eventually.Command) string

	// EventMapper should return the Domain Event type you defined for these commands.
	//
	// NOTE: this is necessary for (de)-serialization purposes while generics are
	// still missing in Go. This requirement might be removed in the future.
	EventMapper func(err error, cmd eventually.Command) eventually.Payload
}

ErrorRecorder is a command.Handler extension that records command handling failures on a Domain Event.

This is useful for always logging command results on the Event Store, which would normally not be done in case of command failures, and to potentially build Saga Process Managers on top of these errors for retries and other domain-specific logic.

func (ErrorRecorder) Handle

func (er ErrorRecorder) Handle(ctx context.Context, cmd eventually.Command) error

Handle delegates command handling to the internal Command Handler and, in case of failure, appends the error and command to the Event Store using the user-provided EventMapper.

If CaptureError has been set to "false", the error coming from the command.Handler will be returned to the caller.

If CaptureError has been set to "true", the error from the command.Handler is silenced but an error can still be returned if the append operation on the Event Store fails.

type Handler

type Handler interface {
	// CommandType returns an empty instance of the Command type the Handler
	// is supposed to handle.
	CommandType() Command

	// Handle receives a Domain Command and executes the necessary business logic.
	//
	// Since Commands' responsibility is only to trigger side effects, and not
	// answering Domain Queries, the Handle method only returns an error, whether
	// the Command has failed execution or not.
	Handle(context.Context, eventually.Command) error
}

Handler is the interface that defines a Command Handler, component that receives a specific kind of Command and executes the business logic related to that particular Command.

type HandlerFunc

type HandlerFunc func(context.Context, eventually.Command) error

HandlerFunc is a functional Command Handler.

func (HandlerFunc) CommandType

func (fn HandlerFunc) CommandType() Command

CommandType returns nil.

Make sure not to use HandlerFunc in a command.Dispatcher, because it will probably require this function to return a meaningful value.

func (HandlerFunc) Handle

func (fn HandlerFunc) Handle(ctx context.Context, cmd eventually.Command) error

Handle executes the functional Command Handler.

type InMemoryDispatcher

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

InMemoryDispatcher is a in-memory Command Dispatcher implementation that allows to register Command Handlers and dispatch Domain Commands.

Use NewInMemoryDispatcher to create a new InMemoryDispatcher instance.

func NewInMemoryDispatcher

func NewInMemoryDispatcher() InMemoryDispatcher

NewInMemoryDispatcher returns a new instance of InMemoryDispatcher.

func (InMemoryDispatcher) Dispatch

func (d InMemoryDispatcher) Dispatch(ctx context.Context, cmd eventually.Command) error

Dispatch accepts incoming Domain Commands and route them to their appropriate Command Handlers, if registered.

An error is returned if no Command Handler has been registered for the Domain Command submitted.

Dispatching strategy for InMemoryDispatcher is synchronous, meaning that the Dispatch method returns when the Command Handler finished execution. If the Command Handler fails execution, returning an error, this error is also returned by the Dispatch invocation.

func (InMemoryDispatcher) Register

func (d InMemoryDispatcher) Register(handler Handler)

Register adds the specified Command Handler into the InMemoryDispatcher routing table, so as to be able to start dispatching Commands to the Handler when calling Dispatch.

Please note, when registering multiple Handlers accepting the same Command type, the last registration will overwrite any previous Handler registration, as this InMemoryDispatcher does not support voting.

type TrackingDispatcher

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

TrackingDispatcher is a fake component that can be used as a command.Dispatcher instance, but keeps the received command in-memory.

Useful for testing, this implementation is thread-safe.

func NewTrackingDispatcher

func NewTrackingDispatcher() *TrackingDispatcher

NewTrackingDispatcher creates a new instance of a fake in-memory command.Dispatcher.

func (*TrackingDispatcher) Dispatch

func (cd *TrackingDispatcher) Dispatch(ctx context.Context, cmd eventually.Command) error

Dispatch records the provided Command internally.

func (*TrackingDispatcher) FlushCommands

func (cd *TrackingDispatcher) FlushCommands() []eventually.Command

FlushCommands returns the list of Commands recorded by the dispatcher and resets the internal list to nil.

func (*TrackingDispatcher) RecordedCommands

func (cd *TrackingDispatcher) RecordedCommands() []eventually.Command

RecordedCommands returns the list of Commands recorded by the dispatcher.

Jump to

Keyboard shortcuts

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