Write dispatcher, change SetOption arguments
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
package stack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/errors"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
const (
|
||||
NameDispatcher = "disp"
|
||||
)
|
||||
|
||||
// Dispatcher grabs a bunch of Dispatchables and groups them into one Handler.
|
||||
//
|
||||
// It will route tx to the proper locations and also allows them to call each
|
||||
// other synchronously through the same tx methods.
|
||||
type Dispatcher struct {
|
||||
routes map[string]Dispatchable
|
||||
}
|
||||
|
||||
func NewDispatcher(routes ...Dispatchable) *Dispatcher {
|
||||
d := &Dispatcher{}
|
||||
d.AddRoutes(routes...)
|
||||
return d
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = new(Dispatcher)
|
||||
|
||||
// AddRoutes registers all these dispatchable choices under their subdomains
|
||||
//
|
||||
// Panics on attempt to double-register a route name, as this is a configuration error.
|
||||
// Should I retrun an error instead?
|
||||
func (d *Dispatcher) AddRoutes(routes ...Dispatchable) {
|
||||
for _, r := range routes {
|
||||
name := r.Name()
|
||||
if _, ok := d.routes[name]; ok {
|
||||
panic(fmt.Sprintf("%s already registered with dispatcher", name))
|
||||
}
|
||||
d.routes[name] = r
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dispatcher) Name() string {
|
||||
return NameDispatcher
|
||||
}
|
||||
|
||||
func (d *Dispatcher) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
|
||||
r, err := d.lookupTx(tx)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// TODO: callback
|
||||
return r.CheckTx(ctx, store, tx, nil)
|
||||
}
|
||||
|
||||
func (d *Dispatcher) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
|
||||
r, err := d.lookupTx(tx)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// TODO: callback
|
||||
return r.DeliverTx(ctx, store, tx, nil)
|
||||
}
|
||||
|
||||
func (d *Dispatcher) SetOption(l log.Logger, store types.KVStore, module, key, value string) (string, error) {
|
||||
r, err := d.lookupModule(module)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// TODO: callback
|
||||
return r.SetOption(l, store, module, key, value, nil)
|
||||
}
|
||||
|
||||
func (d *Dispatcher) lookupTx(tx basecoin.Tx) (Dispatchable, error) {
|
||||
// TODO
|
||||
name := "foo"
|
||||
r, ok := d.routes[name]
|
||||
if !ok {
|
||||
return nil, errors.ErrUnknownTxType(tx)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (d *Dispatcher) lookupModule(name string) (Dispatchable, error) {
|
||||
r, ok := d.routes[name]
|
||||
if !ok {
|
||||
return nil, errors.ErrUnknownModule(name)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
+43
-6
@@ -39,13 +39,13 @@ func (d DeliverMiddleFunc) DeliverTx(ctx basecoin.Context, store types.KVStore,
|
||||
}
|
||||
|
||||
type SetOptionMiddle interface {
|
||||
SetOption(l log.Logger, store types.KVStore, key, value string, next basecoin.SetOptioner) (string, error)
|
||||
SetOption(l log.Logger, store types.KVStore, module, key, value string, next basecoin.SetOptioner) (string, error)
|
||||
}
|
||||
|
||||
type SetOptionMiddleFunc func(log.Logger, types.KVStore, string, string, basecoin.SetOptioner) (string, error)
|
||||
type SetOptionMiddleFunc func(log.Logger, types.KVStore, string, string, string, basecoin.SetOptioner) (string, error)
|
||||
|
||||
func (c SetOptionMiddleFunc) SetOption(l log.Logger, store types.KVStore, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
return c(l, store, key, value, next)
|
||||
func (c SetOptionMiddleFunc) SetOption(l log.Logger, store types.KVStore, module, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
return c(l, store, module, key, value, next)
|
||||
}
|
||||
|
||||
// holders
|
||||
@@ -63,6 +63,43 @@ func (_ PassDeliver) DeliverTx(ctx basecoin.Context, store types.KVStore, tx bas
|
||||
|
||||
type PassOption struct{}
|
||||
|
||||
func (_ PassOption) SetOption(l log.Logger, store types.KVStore, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
return next.SetOption(l, store, key, value)
|
||||
func (_ PassOption) SetOption(l log.Logger, store types.KVStore, module, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
return next.SetOption(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// Dispatchable is like middleware, except the meaning of "next" is different.
|
||||
// Whereas in the middleware, it is the next handler that we should pass the same tx into,
|
||||
// for dispatchers, it is a dispatcher, which it can use to
|
||||
type Dispatchable interface {
|
||||
Middleware
|
||||
AssertDispatcher()
|
||||
}
|
||||
|
||||
// WrapHandler turns a basecoin.Handler into a Dispatchable interface
|
||||
func WrapHandler(h basecoin.Handler) Dispatchable {
|
||||
return wrapped{h}
|
||||
}
|
||||
|
||||
type wrapped struct {
|
||||
h basecoin.Handler
|
||||
}
|
||||
|
||||
var _ Dispatchable = wrapped{}
|
||||
|
||||
func (w wrapped) AssertDispatcher() {}
|
||||
|
||||
func (w wrapped) Name() string {
|
||||
return w.h.Name()
|
||||
}
|
||||
|
||||
func (w wrapped) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, _ basecoin.Checker) (basecoin.Result, error) {
|
||||
return w.h.CheckTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
func (w wrapped) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, _ basecoin.Deliver) (basecoin.Result, error) {
|
||||
return w.h.DeliverTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
func (w wrapped) SetOption(l log.Logger, store types.KVStore, module, key, value string, _ basecoin.SetOptioner) (string, error) {
|
||||
return w.h.SetOption(l, store, module, key, value)
|
||||
}
|
||||
|
||||
+3
-3
@@ -50,12 +50,12 @@ func (_ Logger) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin
|
||||
return
|
||||
}
|
||||
|
||||
func (_ Logger) SetOption(l log.Logger, store types.KVStore, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
func (_ Logger) SetOption(l log.Logger, store types.KVStore, module, key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
start := time.Now()
|
||||
res, err := next.SetOption(l, store, key, value)
|
||||
res, err := next.SetOption(l, store, module, key, value)
|
||||
delta := time.Now().Sub(start)
|
||||
// TODO: log the value being set also?
|
||||
l = l.With("duration", micros(delta)).With("key", key)
|
||||
l = l.With("duration", micros(delta)).With("mod", module).With("key", key)
|
||||
if err == nil {
|
||||
l.Info("SetOption", "log", res)
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -39,8 +39,8 @@ func (m *middleware) DeliverTx(ctx basecoin.Context, store types.KVStore, tx bas
|
||||
return m.middleware.DeliverTx(ctx, store, tx, next)
|
||||
}
|
||||
|
||||
func (m *middleware) SetOption(l log.Logger, store types.KVStore, key, value string) (string, error) {
|
||||
return m.middleware.SetOption(l, store, key, value, m.next)
|
||||
func (m *middleware) SetOption(l log.Logger, store types.KVStore, module, key, value string) (string, error) {
|
||||
return m.middleware.SetOption(l, store, module, key, value, m.next)
|
||||
}
|
||||
|
||||
// Stack is the entire application stack
|
||||
|
||||
+2
-2
@@ -41,13 +41,13 @@ func (_ Recovery) DeliverTx(ctx basecoin.Context, store types.KVStore, tx baseco
|
||||
return next.DeliverTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
func (_ Recovery) SetOption(l log.Logger, store types.KVStore, key, value string, next basecoin.SetOptioner) (log string, err error) {
|
||||
func (_ Recovery) SetOption(l log.Logger, store types.KVStore, module, key, value string, next basecoin.SetOptioner) (log string, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = normalizePanic(r)
|
||||
}
|
||||
}()
|
||||
return next.SetOption(l, store, key, value)
|
||||
return next.SetOption(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// normalizePanic makes sure we can get a nice TMError (with stack) out of it
|
||||
|
||||
Reference in New Issue
Block a user