Move middleware interface into stack, testable handlers
This commit is contained in:
parent
4d0db39fb9
commit
7b5e41adf6
22
handler.go
22
handler.go
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
const (
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue