made copying router, than copies messages (and contexts) it sees to memory, and then re-routes it to the sub-router it was given.
parent
f747012ad3
commit
4b4695769b
|
@ -0,0 +1,51 @@
|
|||
package flog
|
||||
|
||||
|
||||
// NewCopyingRouter returns an initialized CopyingRouter.
|
||||
func NewCopyingRouter(subrouter Router) *CopyingRouter {
|
||||
copies := make([]struct{Message string ; Context map[string]interface{}}, 0, 8)
|
||||
|
||||
router := CopyingRouter {
|
||||
subrouter:subrouter,
|
||||
copies:copies,
|
||||
}
|
||||
|
||||
return &router
|
||||
}
|
||||
|
||||
|
||||
// CopyingRouter is a Router that copies a message (and its context) to memory, and then
|
||||
// re-routes a message (and its context) to a sub-router.
|
||||
//
|
||||
// This router is NOT designed to be used for an indefinite number of routings, and instead
|
||||
// should only be used for a limited amount of routings, as it stores all the copies in
|
||||
// memory.
|
||||
type CopyingRouter struct {
|
||||
subrouter Router
|
||||
copies []struct{Message string ; Context map[string]interface{}}
|
||||
}
|
||||
|
||||
|
||||
func (router *CopyingRouter) Route(message string, context map[string]interface{}) error {
|
||||
copy := struct{Message string ; Context map[string]interface{}}{
|
||||
Message: message,
|
||||
Context: context,
|
||||
}
|
||||
router.copies = append(router.copies, copy)
|
||||
|
||||
return router.subrouter.Route(message, context)
|
||||
}
|
||||
|
||||
|
||||
func (router *CopyingRouter) Copies() <-chan struct{Message string ; Context map[string]interface{}} {
|
||||
ch := make(chan struct{Message string ; Context map[string]interface{}})
|
||||
|
||||
go func() {
|
||||
for _, copy := range router.copies {
|
||||
ch <- copy
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package flog
|
||||
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
func TestNewCopyingRouter(t *testing.T) {
|
||||
|
||||
randomness := rand.New(rand.NewSource( time.Now().UTC().UnixNano() ))
|
||||
|
||||
|
||||
router := NewCopyingRouter(NewDiscardRouter())
|
||||
if nil == router {
|
||||
t.Errorf("After trying to create a copying router, expected it to be not nil, but was: %v", router)
|
||||
}
|
||||
|
||||
|
||||
lenInitialCopies := 0
|
||||
for range router.Copies() {
|
||||
lenInitialCopies++
|
||||
}
|
||||
if expected, actual := 0, lenInitialCopies; expected != actual {
|
||||
t.Errorf("After creating a copying router, expected copies to be length %d, but was actually %d,", expected, actual)
|
||||
}
|
||||
|
||||
|
||||
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 TestCopyingRouterRoute(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
Data []struct{Message string ; Context map[string]interface{}}
|
||||
}{
|
||||
{
|
||||
Data: []struct{Message string ; Context map[string]interface{}}{
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
Data: []struct{Message string ; Context map[string]interface{}}{
|
||||
struct{Message string ; Context map[string]interface{}}{
|
||||
Message: "apple banana cherry",
|
||||
Context: map[string]interface{}{
|
||||
"one":1,
|
||||
"two":2,
|
||||
"three":3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
Data: []struct{Message string ; Context map[string]interface{}}{
|
||||
struct{Message string ; Context map[string]interface{}}{
|
||||
Message: "apple",
|
||||
Context: map[string]interface{}{
|
||||
"one":1,
|
||||
},
|
||||
},
|
||||
struct{Message string ; Context map[string]interface{}}{
|
||||
Message: "banana",
|
||||
Context: map[string]interface{}{
|
||||
"two":2,
|
||||
},
|
||||
},
|
||||
struct{Message string ; Context map[string]interface{}}{
|
||||
Message: "cherry",
|
||||
Context: map[string]interface{}{
|
||||
"cherry":3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
TLoop: for testNumber, test := range tests {
|
||||
|
||||
router := NewCopyingRouter(NewDiscardRouter())
|
||||
|
||||
for _, datum := range test.Data {
|
||||
router.Route(datum.Message, datum.Context)
|
||||
}
|
||||
|
||||
|
||||
lenCopies := 0
|
||||
for range router.Copies() {
|
||||
lenCopies++
|
||||
}
|
||||
if expected, actual := len(test.Data), lenCopies; expected != actual {
|
||||
t.Errorf("For test #%d, after creating a copying router and (potentially) doing some routing, expected copies to be length %d, but was actually %d.", testNumber, expected, actual)
|
||||
continue TLoop
|
||||
}
|
||||
|
||||
|
||||
datumNumber := 0
|
||||
for actualDatum := range router.Copies() {
|
||||
if expected, actual := test.Data[datumNumber].Message, actualDatum.Message; expected != actual {
|
||||
t.Errorf("For test #%d, after creating a copying router and (potentially) doing some routing, expected message for copies datum #%d to be %q, but was actually %q.", testNumber, datumNumber, expected, actual)
|
||||
continue TLoop
|
||||
}
|
||||
|
||||
if expected, actual := len(test.Data[datumNumber].Context), len(actualDatum.Context); expected != actual {
|
||||
t.Errorf("For test #%d, after creating a copying router and (potentially) doing some routing, expected length of context for copies datum #%d to be %d, but was actually %d.", testNumber, datumNumber, expected, actual)
|
||||
continue TLoop
|
||||
}
|
||||
|
||||
for expectedKey, expectedValue := range test.Data[datumNumber].Context {
|
||||
if _, ok := actualDatum.Context[expectedKey]; !ok {
|
||||
t.Errorf("For test #%d, after creating a copying router and (potentially) doing some routing, expected context for copies datum #%d to have key %q, but didn't.", testNumber, datumNumber, expectedKey)
|
||||
continue TLoop
|
||||
}
|
||||
|
||||
if actualValue := actualDatum.Context[expectedKey]; expectedValue != actualValue {
|
||||
t.Errorf("For test #%d, after creating a copying router and (potentially) doing some routing, expected value for context for copies datum #%d at key %q to have value [%v], but actually had [%v].", testNumber, datumNumber, expectedKey, expectedValue, actualValue)
|
||||
continue TLoop
|
||||
}
|
||||
}
|
||||
|
||||
datumNumber++
|
||||
}
|
||||
}
|
||||
}
|
7
flog.go
7
flog.go
|
@ -2,8 +2,6 @@ package flog
|
|||
|
||||
|
||||
type internalFlogger struct {
|
||||
//@TODO: Do we really want this here?
|
||||
// logs []string
|
||||
context map[string]interface{}
|
||||
router Router
|
||||
}
|
||||
|
@ -11,14 +9,9 @@ type internalFlogger struct {
|
|||
|
||||
// New returns an initialized Flogger.
|
||||
func New(router Router, cascade ...interface{}) Flogger {
|
||||
//@TODO: Do we really want this here?
|
||||
// logs := make([]string, 0, 8)
|
||||
|
||||
context := newContext(cascade...)
|
||||
|
||||
flogger := internalFlogger{
|
||||
//@TODO: Do we really want this here?
|
||||
// logs:logs,
|
||||
context:context,
|
||||
router:router,
|
||||
}
|
||||
|
|
6
print.go
6
print.go
|
@ -9,8 +9,6 @@ import (
|
|||
func (flogger *internalFlogger) Print(v ...interface{}) {
|
||||
|
||||
msg := fmt.Sprint(v...)
|
||||
//@TODO: Do we really want this here?
|
||||
// flogger.logs = append(flogger.logs, msg)
|
||||
|
||||
flogger.router.Route(msg, flogger.context)
|
||||
}
|
||||
|
@ -18,8 +16,6 @@ func (flogger *internalFlogger) Print(v ...interface{}) {
|
|||
func (flogger *internalFlogger) Printf(format string, v ...interface{}) {
|
||||
|
||||
msg := fmt.Sprintf(format, v...)
|
||||
//@TODO: Do we really want this here?
|
||||
// flogger.logs = append(flogger.logs, msg)
|
||||
|
||||
flogger.router.Route(msg, flogger.context)
|
||||
}
|
||||
|
@ -27,8 +23,6 @@ func (flogger *internalFlogger) Printf(format string, v ...interface{}) {
|
|||
func (flogger *internalFlogger) Println(v ...interface{}) {
|
||||
|
||||
msg := fmt.Sprintln(v...)
|
||||
//@TODO: Do we really want this here?
|
||||
// flogger.logs = append(flogger.logs, msg)
|
||||
|
||||
flogger.router.Route(msg, flogger.context)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue