created FanoutRouter

master
Charles Iliya Krempeaux 2015-10-10 14:45:21 -07:00
parent 5c15d262cf
commit cab767a0c9
2 changed files with 390 additions and 0 deletions

40
fanout_router.go 100644
View File

@ -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
}

View File

@ -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
}
}