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 {
|
type internalFlogger struct {
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// logs []string
|
|
||||||
context map[string]interface{}
|
context map[string]interface{}
|
||||||
router Router
|
router Router
|
||||||
}
|
}
|
||||||
|
@ -11,14 +9,9 @@ type internalFlogger struct {
|
||||||
|
|
||||||
// New returns an initialized Flogger.
|
// New returns an initialized Flogger.
|
||||||
func New(router Router, cascade ...interface{}) Flogger {
|
func New(router Router, cascade ...interface{}) Flogger {
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// logs := make([]string, 0, 8)
|
|
||||||
|
|
||||||
context := newContext(cascade...)
|
context := newContext(cascade...)
|
||||||
|
|
||||||
flogger := internalFlogger{
|
flogger := internalFlogger{
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// logs:logs,
|
|
||||||
context:context,
|
context:context,
|
||||||
router:router,
|
router:router,
|
||||||
}
|
}
|
||||||
|
|
6
print.go
6
print.go
|
@ -9,8 +9,6 @@ import (
|
||||||
func (flogger *internalFlogger) Print(v ...interface{}) {
|
func (flogger *internalFlogger) Print(v ...interface{}) {
|
||||||
|
|
||||||
msg := fmt.Sprint(v...)
|
msg := fmt.Sprint(v...)
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// flogger.logs = append(flogger.logs, msg)
|
|
||||||
|
|
||||||
flogger.router.Route(msg, flogger.context)
|
flogger.router.Route(msg, flogger.context)
|
||||||
}
|
}
|
||||||
|
@ -18,8 +16,6 @@ func (flogger *internalFlogger) Print(v ...interface{}) {
|
||||||
func (flogger *internalFlogger) Printf(format string, v ...interface{}) {
|
func (flogger *internalFlogger) Printf(format string, v ...interface{}) {
|
||||||
|
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// flogger.logs = append(flogger.logs, msg)
|
|
||||||
|
|
||||||
flogger.router.Route(msg, flogger.context)
|
flogger.router.Route(msg, flogger.context)
|
||||||
}
|
}
|
||||||
|
@ -27,8 +23,6 @@ func (flogger *internalFlogger) Printf(format string, v ...interface{}) {
|
||||||
func (flogger *internalFlogger) Println(v ...interface{}) {
|
func (flogger *internalFlogger) Println(v ...interface{}) {
|
||||||
|
|
||||||
msg := fmt.Sprintln(v...)
|
msg := fmt.Sprintln(v...)
|
||||||
//@TODO: Do we really want this here?
|
|
||||||
// flogger.logs = append(flogger.logs, msg)
|
|
||||||
|
|
||||||
flogger.router.Route(msg, flogger.context)
|
flogger.router.Route(msg, flogger.context)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue