package cqrs import ( "context" ) type Dispatcher struct { reg *Registry cmdFactory CommandFactory cmdResultFactory CommandResultFactory qryFactory QueryFactory qryResultFactory QueryResultFactory } func (d *Dispatcher) Exec(ctx context.Context, req CommandRequest) (CommandResult, error) { cmd, err := d.cmdFactory(req) if err != nil { return nil, err } hdlr, mdlwrs, err := d.reg.MatchCommand(cmd) if err != nil { return nil, err } if len(mdlwrs) > 0 { for i := len(mdlwrs) - 1; i >= 0; i-- { hdlr = mdlwrs[i](hdlr) } } if err := hdlr.Handle(ctx, cmd); err != nil { return nil, err } result, err := d.cmdResultFactory(cmd) if err != nil { return nil, err } return result, nil } func (d *Dispatcher) Query(ctx context.Context, req QueryRequest) (QueryResult, error) { qry, err := d.qryFactory(req) if err != nil { return nil, err } hdlr, mdlwrs, err := d.reg.MatchQuery(qry) if err != nil { return nil, err } if len(mdlwrs) > 0 { for i := len(mdlwrs) - 1; i >= 0; i-- { hdlr = mdlwrs[i](hdlr) } } data, err := hdlr.Handle(ctx, qry) if err != nil { return nil, err } result, err := d.qryResultFactory(qry, data) if err != nil { return nil, err } return result, nil } func (d *Dispatcher) RegisterCommand(match MatchFunc, hdlr CommandHandler, mdlwrs ...CommandMiddleware) { d.reg.RegisterCommand(match, hdlr, mdlwrs...) } func (d *Dispatcher) RegisterQuery(match MatchFunc, hdlr QueryHandler, mdlwrs ...QueryMiddleware) { d.reg.RegisterQuery(match, hdlr, mdlwrs...) } func NewDispatcher(funcs ...OptionFunc) *Dispatcher { opt := CreateOption(funcs...) return &Dispatcher{ reg: NewRegistry(), cmdFactory: opt.CommandFactory, cmdResultFactory: opt.CommandResultFactory, qryFactory: opt.QueryFactory, qryResultFactory: opt.QueryResultFactory, } }