Skip to content

Commit

Permalink
refactor: ♻️ some refactoring in cqrs
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdihadeli committed Jan 7, 2024
1 parent 5ff36d2 commit 03a94a7
Show file tree
Hide file tree
Showing 78 changed files with 1,288 additions and 651 deletions.
28 changes: 28 additions & 0 deletions internal/pkg/core/cqrs/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cqrs

type command struct {
TypeInfo
}

type Command interface {
isCommand()

TypeInfo
}

func NewCommandByT[T any]() Command {
c := &command{TypeInfo: NewTypeInfoT[T]()}

return c
}

func (c *command) isCommand() {
}

func IsCommand(obj interface{}) bool {
if _, ok := obj.(Command); ok {
return true
}

return false
}
15 changes: 15 additions & 0 deletions internal/pkg/core/cqrs/command_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cqrs

import (
"context"

"github.com/mehdihadeli/go-mediatr"
)

type CommandHandler[TCommand Command, TResponse any] interface {
Handle(ctx context.Context, command TCommand) (TResponse, error)
}

type CommandHandlerVoid[TCommand Command] interface {
Handle(ctx context.Context, command TCommand) (*mediatr.Unit, error)
}
44 changes: 44 additions & 0 deletions internal/pkg/core/cqrs/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cqrs

import (
"testing"
"time"

"github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper"

"github.com/brianvoe/gofakeit/v6"
uuid "github.com/satori/go.uuid"
"github.com/stretchr/testify/assert"
)

func Test_Command(t *testing.T) {
command := &CreateProductTest{
Command: NewCommandByT[*CreateProductTest](),
ProductID: uuid.NewV4(),
Name: gofakeit.Name(),
CreatedAt: time.Now(),
Description: gofakeit.AdjectiveDescriptive(),
Price: gofakeit.Price(100, 1000),
}

isImplementedCommand := typemapper.ImplementedInterfaceT[Command](command)
assert.True(t, isImplementedCommand)

var i interface{} = command
_, ok := i.(Command)
_, ok2 := i.(TypeInfo)
assert.True(t, ok)
assert.True(t, ok2)
assert.Equal(t, command.ShortTypeName(), "*CreateProductTest")
assert.Equal(t, command.FullTypeName(), "*cqrs.CreateProductTest")
}

type CreateProductTest struct {
Command

Name string
ProductID uuid.UUID
Description string
Price float64
CreatedAt time.Time
}
25 changes: 25 additions & 0 deletions internal/pkg/core/cqrs/internal_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cqrs

type internalCommand struct {
Command
}

type InternalCommand interface {
Command
isInternalCommand()
}

func NewInternalCommandByT[T any]() InternalCommand {
return &internalCommand{Command: NewCommandByT[T]()}
}

func (c *internalCommand) isInternalCommand() {
}

func IsInternalCommand(obj interface{}) bool {
if _, ok := obj.(InternalCommand); ok {
return true
}

return false
}
1 change: 1 addition & 0 deletions internal/pkg/core/cqrs/internal_command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package cqrs
25 changes: 25 additions & 0 deletions internal/pkg/core/cqrs/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cqrs

type query struct {
TypeInfo
}

type Query interface {
TypeInfo
isQuery()
}

func NewQueryByT[T any]() Query {
return &query{TypeInfo: NewTypeInfoT[T]()}
}

func (q *query) isQuery() {
}

func IsQuery(obj interface{}) bool {
if _, ok := obj.(Query); ok {
return true
}

return false
}
9 changes: 9 additions & 0 deletions internal/pkg/core/cqrs/query_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cqrs

import (
"context"
)

type QueryHandler[TQuery Query, TResponse any] interface {
Handle(ctx context.Context, query TQuery) (TResponse, error)
}
38 changes: 38 additions & 0 deletions internal/pkg/core/cqrs/query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cqrs

import (
"testing"

uuid "github.com/satori/go.uuid"
"github.com/stretchr/testify/assert"
)

func Test_Query(t *testing.T) {
query := &GetProductById{
Query: NewQueryByT[GetProductById](),
ProductID: uuid.NewV4(),
}

assert.True(t, IsQuery(query))
}

//
//func Test_Query_Is_Catstable_To_Command(t *testing.T) {
// var q Query = NewQuery()
// var c Command = commands.NewCommand()
// query, qok := q.(Query)
// command, cok := c.(Command)
// assert.True(t, qok)
// assert.True(t, cok)
// assert.NotNil(t, query)
// assert.NotNil(t, command)
//
// query, qok = command.(Query)
// assert.False(t, qok)
// assert.Nil(t, query)
//}

type GetProductById struct {
Query
ProductID uuid.UUID
}
39 changes: 39 additions & 0 deletions internal/pkg/core/cqrs/type_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cqrs

import (
"reflect"

"github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper"
)

type TypeInfo interface {
ShortTypeName() string
FullTypeName() string
Type() reflect.Type
}

type typeInfo struct {
shortTypeName string
fullTypeName string
typ reflect.Type
}

func NewTypeInfoT[T any]() TypeInfo {
name := typemapper.GetGenericTypeNameByT[T]()
fullName := typemapper.GetGenericFullTypeNameByT[T]()
typ := typemapper.GetGenericTypeByT[T]()

return &typeInfo{fullTypeName: fullName, typ: typ, shortTypeName: name}
}

func (t *typeInfo) ShortTypeName() string {
return t.shortTypeName
}

func (t *typeInfo) FullTypeName() string {
return t.fullTypeName
}

func (t *typeInfo) Type() reflect.Type {
return t.typ
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func StartConsumerSpan(
opts := getTraceOptions(meta, payload, consumerTracingOptions)

// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/messaging.md#span-name
// SpanName = Destination Name + Operation Name
// SpanName = Destination ShortTypeName + Operation ShortTypeName
ctx, span := tracing.MessagingTracer.Start(
parentSpanContext,
fmt.Sprintf("%s %s", consumerTracingOptions.Destination, "receive"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func StartProducerSpan(
opts := getTraceOptions(meta, message, payload, producerTracingOptions)

// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/messaging.md#span-name
// SpanName = Destination Name + Operation Name
// SpanName = Destination ShortTypeName + Operation ShortTypeName
ctx, span := tracing.MessagingTracer.Start(
parentSpanContext,
fmt.Sprintf("%s %s", producerTracingOptions.Destination, "send"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
uuid "github.com/satori/go.uuid"
)

type MessageService interface {
type MessagePersistenceService interface {
Add(ctx context.Context, storeMessage *StoreMessage) error
Update(ctx context.Context, storeMessage *StoreMessage) error
ChangeState(
Expand All @@ -27,11 +27,15 @@ type MessageService interface {
Process(messageID string, ctx context.Context) error
ProcessAll(ctx context.Context) error
AddPublishMessage(
messageEnvelope types.MessageEnvelopeTMessage,
messageEnvelope types.MessageEnvelope,
ctx context.Context,
) error
AddReceivedMessage(
messageEnvelope types.MessageEnvelope,
ctx context.Context,
) error
//AddInternalMessage(
// internalCommand InternalMessage,
// ctx context.Context,
//) error
}
6 changes: 3 additions & 3 deletions internal/pkg/core/serializer/json/json_serilizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func Test_Deserialize_Unstructured_Data_Into_Empty_Interface(t *testing.T) {

assert.True(t, reflect.TypeOf(jsonMap).Kind() == reflect.Map)
assert.True(t, reflect.TypeOf(jsonMap) == reflect.TypeOf(map[string]interface{}(nil)))
assert.True(t, jsonMap.(map[string]interface{})["Name"] == "John")
assert.True(t, jsonMap.(map[string]interface{})["ShortTypeName"] == "John")
assert.True(t, jsonMap.(map[string]interface{})["Age"] == float64(30))
}

Expand Down Expand Up @@ -75,7 +75,7 @@ func Test_Deserialize_Unstructured_Data_Into_Map(t *testing.T) {

assert.True(t, reflect.TypeOf(jsonMap).Kind() == reflect.Map)
assert.True(t, reflect.TypeOf(jsonMap) == reflect.TypeOf(map[string]interface{}(nil)))
assert.True(t, jsonMap["Name"] == "John")
assert.True(t, jsonMap["ShortTypeName"] == "John")
assert.True(t, jsonMap["Age"] == float64(30))
}

Expand Down Expand Up @@ -172,6 +172,6 @@ func Test_Decode_To_Map(t *testing.T) {
panic(err)
}

assert.True(t, jsonMap["Name"] == "John")
assert.True(t, jsonMap["ShortTypeName"] == "John")
assert.True(t, jsonMap["Age"] == float64(30))
}
2 changes: 1 addition & 1 deletion internal/pkg/elasticsearch/elastic_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/iancoleman/strcase"
)

var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[ElasticOptions]())
var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[ElasticOptions]())

type ElasticOptions struct {
URL string `mapstructure:"url"`
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/eventstroredb/config/eventstoredb_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ type Subscription struct {
}

func ProvideConfig(environment environment.Environment) (*EventStoreDbOptions, error) {
optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[EventStoreDbOptions]())
optionName := strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[EventStoreDbOptions]())
return config.BindConfigKey[*EventStoreDbOptions](optionName, environment)
}
4 changes: 2 additions & 2 deletions internal/pkg/grpc/config/grpc_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/iancoleman/strcase"
)

var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[GrpcOptions]())
var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[GrpcOptions]())

type GrpcOptions struct {
Port string `mapstructure:"port" env:"TcpPort"`
Host string `mapstructure:"host" env:"Host"`
Development bool `mapstructure:"development" env:"Development"`
Name string `mapstructure:"name" env:"Name"`
Name string `mapstructure:"name" env:"ShortTypeName"`
}

func ProvideConfig(environment environment.Environment) (*GrpcOptions, error) {
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/http/customecho/config/echo_http_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/iancoleman/strcase"
)

var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[EchoHttpOptions]())
var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[EchoHttpOptions]())

type EchoHttpOptions struct {
Port string `mapstructure:"port" validate:"required" env:"TcpPort"`
Expand All @@ -21,7 +21,7 @@ type EchoHttpOptions struct {
IgnoreLogUrls []string `mapstructure:"ignoreLogUrls"`
Timeout int `mapstructure:"timeout" env:"Timeout"`
Host string `mapstructure:"host" env:"Host"`
Name string `mapstructure:"name" env:"Name"`
Name string `mapstructure:"name" env:"ShortTypeName"`
}

func (c *EchoHttpOptions) Address() string {
Expand Down
Loading

0 comments on commit 03a94a7

Please sign in to comment.