Documentation
¶
Overview ¶
Package commandlog provides an interface and middleware for recording every command dispatched through a CommandBus. This is a "bricks" package — bring your own backend by implementing CommandLogStore, or use a provided one.
The middleware wraps command dispatch to capture:
- The command payload before execution (status: "pending")
- The outcome after execution (accepted/rejected/failed, produced event IDs, duration)
Typical usage:
store := memlog.New() bus.Use(commandlog.Middleware(store))
Index ¶
- Constants
- Variables
- func Middleware(store CommandLogStore, opts ...MiddlewareOption) command.Middleware
- type CommandLogStore
- type CommandRecord
- type IDFunc
- type MiddlewareOption
- func WithCorrelationFunc(fn func(ctx context.Context, cmd command.Command) string) MiddlewareOption
- func WithEventIDsFunc(fn func(result *command.Result) []string) MiddlewareOption
- func WithIDFunc(fn IDFunc) MiddlewareOption
- func WithMetadataFunc(fn func(ctx context.Context, cmd command.Command) map[string]string) MiddlewareOption
- type QueryOpts
Constants ¶
const ( // MaxPayloadBytes is the upper bound on Payload size (1 MB). MaxPayloadBytes = 1 << 20 // MaxMetadataKeys is the upper bound on Metadata entries. MaxMetadataKeys = 256 // MaxEventIDs is the upper bound on EventIDs per record. MaxEventIDs = 10000 // MaxErrorLength is the upper bound on the Error string. MaxErrorLength = 8192 // MaxQueryLimit caps the number of records returned by a single query. MaxQueryLimit = 10000 // DefaultQueryLimit is used when QueryOpts.Limit is zero. DefaultQueryLimit = 100 )
Bounds — TigerStyle: every resource must be bounded.
const ( StatusPending = "pending" StatusAccepted = "accepted" StatusRejected = "rejected" StatusFailed = "failed" )
Status constants for CommandRecord.Status.
Variables ¶
var ( // ErrNotFound is returned by Get when no record matches the given ID. ErrNotFound = errors.New("commandlog: record not found") // ErrDuplicateID is returned by Record when the ID already exists. ErrDuplicateID = errors.New("commandlog: duplicate record ID") )
Sentinel errors for CommandLogStore implementations.
Functions ¶
func Middleware ¶
func Middleware(store CommandLogStore, opts ...MiddlewareOption) command.Middleware
Middleware returns a command.Middleware that logs every command to the given store. Commands are recorded before execution (pending) and updated after (accepted/rejected/failed).
Types ¶
type CommandLogStore ¶
type CommandLogStore interface {
// Record persists a command record. The record's ID must be unique.
Record(ctx context.Context, record CommandRecord) error
// Get retrieves a single record by ID. Returns ErrNotFound if absent.
Get(ctx context.Context, id string) (CommandRecord, error)
// FindByCorrelation returns all records sharing a correlation ID, ordered by Timestamp.
FindByCorrelation(ctx context.Context, correlationID string) ([]CommandRecord, error)
// FindByType returns records matching the command type, filtered by opts.
FindByType(ctx context.Context, commandType string, opts QueryOpts) ([]CommandRecord, error)
// List returns records ordered by Timestamp descending, filtered by opts.
List(ctx context.Context, opts QueryOpts) ([]CommandRecord, error)
}
CommandLogStore persists and queries command records. Implementations must be safe for concurrent use.
type CommandRecord ¶
type CommandRecord struct {
// ID uniquely identifies this record.
ID string
// CorrelationID groups related commands (e.g. a saga).
CorrelationID string
// CommandType is the routed command name.
CommandType string
// Payload is the serialized command body. Bounded by MaxPayloadBytes.
Payload []byte
// Metadata holds arbitrary key-value pairs. Bounded by MaxMetadataKeys.
Metadata map[string]string
// Status is the execution outcome: pending, accepted, rejected, or failed.
Status string
// Error holds the error message if Status is rejected or failed.
Error string
// EventIDs lists IDs of events produced by the command. Bounded by MaxEventIDs.
EventIDs []string
// Duration is how long the command took to execute.
Duration time.Duration
// Timestamp is when the command was recorded.
Timestamp time.Time
}
CommandRecord represents a single logged command execution.
type IDFunc ¶
type IDFunc func() string
IDFunc generates unique IDs for command records. Default uses timestamp + random suffix via crypto/rand.
type MiddlewareOption ¶
type MiddlewareOption func(*middlewareConfig)
MiddlewareOption configures the command log middleware.
func WithCorrelationFunc ¶
WithCorrelationFunc extracts a correlation ID from the command context. Default: empty string (no correlation).
func WithEventIDsFunc ¶
func WithEventIDsFunc(fn func(result *command.Result) []string) MiddlewareOption
WithEventIDsFunc extracts event IDs from a command result. Default: nil (no event IDs recorded).
func WithIDFunc ¶
func WithIDFunc(fn IDFunc) MiddlewareOption
WithIDFunc sets a custom ID generator. Default: crypto/rand hex.
func WithMetadataFunc ¶
func WithMetadataFunc(fn func(ctx context.Context, cmd command.Command) map[string]string) MiddlewareOption
WithMetadataFunc extracts metadata from the command context. Default: nil metadata.
type QueryOpts ¶
type QueryOpts struct {
// Limit caps the number of results. Zero means DefaultQueryLimit; capped at MaxQueryLimit.
Limit int
// Offset skips this many results (for pagination).
Offset int
// After filters to records with Timestamp strictly after this time.
After time.Time
// Before filters to records with Timestamp strictly before this time.
Before time.Time
}
QueryOpts controls filtering and pagination for list queries.
func (QueryOpts) EffectiveLimit ¶
EffectiveLimit returns the Limit to use, applying defaults and caps.