Move middleware interface into stack, testable handlers

This commit is contained in:
Ethan Frey 2017-06-29 15:40:26 +02:00
parent 4d0db39fb9
commit 7b5e41adf6
6 changed files with 85 additions and 29 deletions

View File

@ -15,10 +15,6 @@ type Checker interface {
CheckTx(ctx Context, store types.KVStore, tx Tx) (Result, error)
}
type CheckerMiddle interface {
CheckTx(ctx Context, store types.KVStore, tx Tx, next Checker) (Result, error)
}
// CheckerFunc (like http.HandlerFunc) is a shortcut for making wrapers
type CheckerFunc func(Context, types.KVStore, Tx) (Result, error)
@ -26,16 +22,10 @@ func (c CheckerFunc) CheckTx(ctx Context, store types.KVStore, tx Tx) (Result, e
return c(ctx, store, tx)
}
var _ Checker = CheckerFunc(nil)
type Deliver interface {
DeliverTx(ctx Context, store types.KVStore, tx Tx) (Result, error)
}
type DeliverMiddle interface {
DeliverTx(ctx Context, store types.KVStore, tx Tx, next Deliver) (Result, error)
}
// DeliverFunc (like http.HandlerFunc) is a shortcut for making wrapers
type DeliverFunc func(Context, types.KVStore, Tx) (Result, error)
@ -43,8 +33,6 @@ func (c DeliverFunc) DeliverTx(ctx Context, store types.KVStore, tx Tx) (Result,
return c(ctx, store, tx)
}
var _ Deliver = DeliverFunc(nil)
// Handler is anything that processes a transaction
type Handler interface {
Checker
@ -57,16 +45,6 @@ type Handler interface {
// EndBlock(store types.KVStore, height uint64) abci.ResponseEndBlock
}
// Middleware is anything that wraps another handler to enhance functionality.
//
// You can use utilities in handlers to construct them, the interfaces
// are exposed in the top-level package to avoid import loops.
type Middleware interface {
CheckerMiddle
DeliverMiddle
Named
}
// Result captures any non-error abci result
// to make sure people use error for error cases
type Result struct {

View File

@ -3,6 +3,7 @@ package handlers
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/txs"
"github.com/tendermint/basecoin/types"
)
@ -29,7 +30,7 @@ func (_ SimpleFeeHandler) Name() string {
return NameFee
}
var _ basecoin.Middleware = SimpleFeeHandler{}
var _ stack.Middleware = SimpleFeeHandler{}
// Yes, I know refactor a bit... really too late already

View File

@ -5,6 +5,7 @@ import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/types"
)
@ -21,7 +22,7 @@ func (_ SignedHandler) Name() string {
return NameSigs
}
var _ basecoin.Middleware = SignedHandler{}
var _ stack.Middleware = SignedHandler{}
func SigPerm(addr []byte) basecoin.Actor {
return basecoin.NewActor(NameSigs, addr)

View File

@ -1,12 +1,15 @@
package stack
import (
"github.com/pkg/errors"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/types"
)
const (
NameVoid = "void"
NameVoid = "void"
NameFail = "fail"
NamePanic = "panic"
)
// voidHandler just used to return okay to everything
@ -27,3 +30,52 @@ func (_ voidHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basec
func (_ voidHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
return
}
// failHandler always returns an error
type failHandler struct {
err error
}
var _ basecoin.Handler = failHandler{}
func (_ failHandler) Name() string {
return NameFail
}
// CheckTx always returns the given error
func (f failHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
return res, errors.WithStack(f.err)
}
// DeliverTx always returns the given error
func (f failHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
return res, errors.WithStack(f.err)
}
// panicHandler always panics, using the given error (first choice) or msg (fallback)
type panicHandler struct {
msg string
err error
}
var _ basecoin.Handler = panicHandler{}
func (_ panicHandler) Name() string {
return NamePanic
}
// CheckTx always panics
func (p panicHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
if p.err != nil {
panic(p.err)
}
panic(p.msg)
}
// DeliverTx always panics
func (p panicHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
if p.err != nil {
panic(p.err)
}
panic(p.msg)
}

24
stack/interface.go Normal file
View File

@ -0,0 +1,24 @@
package stack
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/types"
)
type CheckerMiddle interface {
CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, next basecoin.Checker) (basecoin.Result, error)
}
type DeliverMiddle interface {
DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, next basecoin.Deliver) (basecoin.Result, error)
}
// Middleware is anything that wraps another handler to enhance functionality.
//
// You can use utilities in handlers to construct them, the interfaces
// are exposed in the top-level package to avoid import loops.
type Middleware interface {
CheckerMiddle
DeliverMiddle
basecoin.Named
}

View File

@ -9,7 +9,7 @@ import (
//
// heavily inspired by negroni's design
type middleware struct {
middleware basecoin.Middleware
middleware Middleware
next basecoin.Handler
}
@ -39,7 +39,7 @@ func (m *middleware) DeliverTx(ctx basecoin.Context, store types.KVStore, tx bas
// Stack is the entire application stack
type Stack struct {
middles []basecoin.Middleware
middles []Middleware
handler basecoin.Handler
basecoin.Handler // the compiled version, which we expose
}
@ -48,7 +48,7 @@ var _ basecoin.Handler = &Stack{}
// NewStack prepares a middleware stack, you must `.Use()` a Handler
// before you can execute it.
func NewStack(middlewares ...basecoin.Middleware) *Stack {
func NewStack(middlewares ...Middleware) *Stack {
return &Stack{
middles: middlewares,
}
@ -64,7 +64,7 @@ func (s *Stack) Use(handler basecoin.Handler) *Stack {
return s
}
func build(mid []basecoin.Middleware, end basecoin.Handler) basecoin.Handler {
func build(mid []Middleware, end basecoin.Handler) basecoin.Handler {
if len(mid) == 0 {
return end
}