Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CQRS marshalers #78

Merged
merged 6 commits into from
May 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe ObjectNameWithoutPackage? it is pretty long, but explicit :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was rather thinking about renaming ObjectName to FullyQualifiedStructName and leave this as is, but ObjectNameWithoutPackage works as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, like I like the idea of FullyQualifiedStructName :)

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.