created FanoutRouter
parent
5c15d262cf
commit
cab767a0c9
|
@ -0,0 +1,40 @@
|
||||||
|
package flog
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/reiver/go-manyerrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// NewFanoutRouter returns an initialized FanoutRouter.
|
||||||
|
func NewFanoutRouter(subrouters ...Router) *FanoutRouter {
|
||||||
|
router := FanoutRouter{
|
||||||
|
subrouters:subrouters,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &router
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FanoutRouter is a Router that re-routes any message (and its context) it
|
||||||
|
// receives to all of its sub-routers.
|
||||||
|
type FanoutRouter struct {
|
||||||
|
subrouters []Router
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (router *FanoutRouter) Route(message string, context map[string]interface{}) error {
|
||||||
|
errors := []error{}
|
||||||
|
|
||||||
|
for _, subrouter := range router.subrouters {
|
||||||
|
if err := subrouter.Route(message, context); nil != err {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 < len(errors) {
|
||||||
|
return manyerrors.New(errors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,350 @@
|
||||||
|
package flog
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/reiver/go-manyerrors"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func TestNewFanoutRouter(t *testing.T) {
|
||||||
|
|
||||||
|
randomness := rand.New(rand.NewSource( time.Now().UTC().UnixNano() ))
|
||||||
|
|
||||||
|
|
||||||
|
router := NewFanoutRouter()
|
||||||
|
if nil == router {
|
||||||
|
t.Errorf("After trying to create a discard router, expected it to be not nil, but was: %v", router)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message := fmt.Sprint("%x", randomness.Int63n(9999999999))
|
||||||
|
|
||||||
|
context := make(map[string]interface{})
|
||||||
|
limit := randomness.Int63n(30)
|
||||||
|
for i:=int64(0); i<limit; i++ {
|
||||||
|
context[ fmt.Sprintf("%x", randomness.Int63n(1000*limit)) ] = fmt.Sprintf("%x", randomness.Int63n(999999999999999))
|
||||||
|
}
|
||||||
|
|
||||||
|
router.Route(message, context) // Just make sure it doesn't panic or deadlok, by calling this.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestFanoutRouterRoute(t *testing.T) {
|
||||||
|
|
||||||
|
numApples := 0
|
||||||
|
numBananas := 0
|
||||||
|
numCherries := 0
|
||||||
|
numFigs := 0
|
||||||
|
numKiwis := 0
|
||||||
|
numApplesOrFigs := 0
|
||||||
|
|
||||||
|
appleRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "apple" == message {
|
||||||
|
numApples++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
bananaRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "banana" == message {
|
||||||
|
numBananas++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
cherryRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "cherry" == message {
|
||||||
|
numCherries++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
figRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "fig" == message {
|
||||||
|
numFigs++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
kiwiRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "kiwi" == message {
|
||||||
|
numKiwis++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
appleOrFigRouter := NewFilteringRouter(NewDiscardingRouter(), func(message string, context map[string]interface{}) bool {
|
||||||
|
if "apple" == message || "fig" == message {
|
||||||
|
numApplesOrFigs++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router := NewFanoutRouter(appleRouter, bananaRouter, cherryRouter, figRouter, kiwiRouter, appleOrFigRouter)
|
||||||
|
|
||||||
|
if expected, actual := 0, numApples; expected != actual {
|
||||||
|
t.Errorf("Initially expected numApples to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numBananas; expected != actual {
|
||||||
|
t.Errorf("Initially expected numBananas to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numCherries; expected != actual {
|
||||||
|
t.Errorf("Initially expected numCherries to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numFigs; expected != actual {
|
||||||
|
t.Errorf("Initially expected numFigs to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numKiwis; expected != actual {
|
||||||
|
t.Errorf("Initially expected numKiwis to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("Initially expected numApplesOrFigs to be %d, but actually was %d.", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var message string
|
||||||
|
var context map[string]interface{} = map[string]interface{}{}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "apple"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "banana"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "cherry"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "fig"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 0, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 2, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "kiwi"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 2, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = "fig"
|
||||||
|
if err := router.Route(message, context); nil != err {
|
||||||
|
switch errs := err.(type) {
|
||||||
|
case manyerrors.Errors:
|
||||||
|
t.Errorf("Received many error when trying to send message %q: %#v", message, errs.Errors())
|
||||||
|
default:
|
||||||
|
t.Errorf("Received error when trying to send message %q: %v", message, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, actual := 1, numApples; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApples to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numBananas; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numBananas to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numCherries; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numCherries to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 2, numFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 1, numKiwis; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numKiwis to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if expected, actual := 3, numApplesOrFigs; expected != actual {
|
||||||
|
t.Errorf("After sending message %q expected numApplesOrFigs to be %d, but actually was %d.", message, expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue