modernice / goes

goes is an event-sourcing framework for Go.
https://goes.modernice.dev
Apache License 2.0
134 stars 12 forks source link

Human-readable command errors #12

Closed bounoable closed 2 years ago

bounoable commented 3 years ago

Provide a method to return a human-readable error from a command handler back to the command dispatcher when using the dispatch.Synchronous option.

Command handler in some service:

package example

func handleCommands(ctx context.Context, bus command.Bus) <-chan error {
    h := command.NewHandler()

    return h.MustHandle(ctx, "foo-cmd", func(ctx command.Context) error {
        cmd := ctx.Command()

        err := errors.New("mock error") // some error returned by domain layer

        return command.Fail(err, "Something went wrong while handling %q command.", cmd.Name())
    })
}

func main() {
    var bus command.Bus

    errs := handleCommands(context.TODO(), bus)

    for err := range errs {
        var cmdErr *command.Error
        errors.As(err, &cmdErr) == true

        err.Error() == `Something went wrong while handling "foo-cmd" command.`
        cmdErr.Unwrap().Error() == "mock error"
    }
}

Command dispatcher in another service:

package example

func dispatchCommand(ctx context.Context, bus command.Bus) {
    cmd := command.New("foo-cmd", ...)

    err := bus.Dispatch(ctx, cmd, dispatch.Synchronous())

    err.Error() == `Something went wrong while handling "foo-cmd" command.`

    var cmdErr *command.Error
    errors.As(err, &cmdErr) == true

    cmdErr.Unwrap().Error() == "mock error"
}
bounoable commented 2 years ago

Commands dispatcher should not rely on responses from the command handlers within other services; they just need to know if the command has been accepted by the handler, which works already. Closing.