Skip to content

Commit

Permalink
Add CQRS marshalers (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
sagikazarmark authored and roblaszczak committed May 25, 2019
1 parent 127d033 commit cc6954d
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 39 deletions.
9 changes: 7 additions & 2 deletions components/cqrs/marshaler_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
)

type JSONMarshaler struct {
NewUUID func() string
NewUUID func() string
GenerateName func(v interface{}) string
}

func (m JSONMarshaler) Marshal(v interface{}) (*message.Message, error) {
Expand Down Expand Up @@ -40,7 +41,11 @@ func (JSONMarshaler) Unmarshal(msg *message.Message, v interface{}) (err error)
}

func (m JSONMarshaler) Name(cmdOrEvent interface{}) string {
return ObjectName(cmdOrEvent)
if m.GenerateName != nil {
return m.GenerateName(cmdOrEvent)
}

return FullyQualifiedStructName(cmdOrEvent)
}

func (m JSONMarshaler) NameFromMessage(msg *message.Message) string {
Expand Down
9 changes: 7 additions & 2 deletions components/cqrs/marshaler_protobuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
)

type ProtobufMarshaler struct {
NewUUID func() string
NewUUID func() string
GenerateName func(v interface{}) string
}

type NoProtoMessageError struct {
Expand Down Expand Up @@ -61,7 +62,11 @@ func (ProtobufMarshaler) Unmarshal(msg *message.Message, v interface{}) (err err
}

func (m ProtobufMarshaler) Name(cmdOrEvent interface{}) string {
return ObjectName(cmdOrEvent)
if m.GenerateName != nil {
return m.GenerateName(cmdOrEvent)
}

return FullyQualifiedStructName(cmdOrEvent)
}

func (m ProtobufMarshaler) NameFromMessage(msg *message.Message) string {
Expand Down
42 changes: 42 additions & 0 deletions components/cqrs/name.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cqrs

import (
"fmt"
"strings"
)

// FullyQualifiedStructName name returns object name in format [package].[type name].
// It ignores if the value is a pointer or not.
func FullyQualifiedStructName(v interface{}) string {
s := fmt.Sprintf("%T", v)
s = strings.TrimLeft(s, "*")

return s
}

// StructName name returns struct name in format [type name].
// It ignores if the value is a pointer or not.
func StructName(v interface{}) string {
segments := strings.Split(fmt.Sprintf("%T", v), ".")

return segments[len(segments)-1]
}

type namedStruct interface {
Name() string
}

// NamedStruct returns the name from a message implementing the following interface:
// type namedStruct interface {
// Name() string
// }
// It ignores if the value is a pointer or not.
func NamedStruct(fallback func(v interface{}) string) func(v interface{}) string {
return func(v interface{}) string {
if v, ok := v.(namedStruct); ok {
return v.Name()
}

return fallback(v)
}
}
49 changes: 49 additions & 0 deletions components/cqrs/name_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cqrs_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/ThreeDotsLabs/watermill/components/cqrs"
)

func TestFullyQualifiedStructName(t *testing.T) {
type Object struct{}

assert.Equal(t, "cqrs_test.Object", cqrs.FullyQualifiedStructName(Object{}))
assert.Equal(t, "cqrs_test.Object", cqrs.FullyQualifiedStructName(&Object{}))
}

func BenchmarkFullyQualifiedStructName(b *testing.B) {
type Object struct{}
o := Object{}

for i := 0; i < b.N; i++ {
cqrs.FullyQualifiedStructName(o)
}
}

func TestStructName(t *testing.T) {
type Object struct{}

assert.Equal(t, "Object", cqrs.StructName(Object{}))
assert.Equal(t, "Object", cqrs.StructName(&Object{}))
}

func TestNamedStruct(t *testing.T) {
assert.Equal(t, "named object", cqrs.NamedStruct(cqrs.StructName)(namedObject{}))
assert.Equal(t, "named object", cqrs.NamedStruct(cqrs.StructName)(&namedObject{}))

// Test fallback
type Object struct{}

assert.Equal(t, "Object", cqrs.NamedStruct(cqrs.StructName)(Object{}))
assert.Equal(t, "Object", cqrs.NamedStruct(cqrs.StructName)(&Object{}))
}

type namedObject struct{}

func (namedObject) Name() string {
return "named object"
}
11 changes: 0 additions & 11 deletions components/cqrs/object.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package cqrs

import (
"fmt"
"reflect"
"strings"
)

func isPointer(v interface{}) error {
Expand All @@ -23,12 +21,3 @@ type NonPointerError struct {
func (e NonPointerError) Error() string {
return "non-pointer command: " + e.Type.String() + ", handler.NewCommand() should return pointer to the command"
}

// ObjectName name returns object name in format [package].[type name].
// It ignores if the value is a pointer or not.
func ObjectName(v interface{}) string {
s := fmt.Sprintf("%T", v)
s = strings.TrimLeft(s, "*")

return s
}
24 changes: 0 additions & 24 deletions components/cqrs/object_test.go

This file was deleted.

0 comments on commit cc6954d

Please sign in to comment.