From 854fbc0b020fb7e62e99dba733982376fb0a6943 Mon Sep 17 00:00:00 2001 From: ehsan Date: Sun, 19 Mar 2023 03:21:42 +0330 Subject: [PATCH] rename --- assets/{Go-MediatR.png => go-mediator.png} | Bin examples/cqrs/cmd/main.go | 34 ++++---- .../products/api/products_controller.go | 14 +-- .../commands/create_product_handler.go | 14 +-- .../dtos/get_product_by_id_response.go | 2 +- .../queries/get_product_by_id_handler.go | 6 +- examples/cqrs/internal/products/mapper.go | 4 +- .../repository/inmemory_product_repository.go | 2 +- .../behaviours/request_logger_behaviour.go | 4 +- go.mod | 4 +- mediatr.go | 34 ++++---- mediatr_benchmarks_test.go | 6 +- mediatr_test.go | 54 ++++++------ readme.md | 82 +++++++++--------- 14 files changed, 129 insertions(+), 131 deletions(-) rename assets/{Go-MediatR.png => go-mediator.png} (100%) diff --git a/assets/Go-MediatR.png b/assets/go-mediator.png similarity index 100% rename from assets/Go-MediatR.png rename to assets/go-mediator.png diff --git a/examples/cqrs/cmd/main.go b/examples/cqrs/cmd/main.go index 91cdb85..354035b 100644 --- a/examples/cqrs/cmd/main.go +++ b/examples/cqrs/cmd/main.go @@ -2,21 +2,21 @@ package main import ( "context" + "github.com/ehsandavari/go-mediator" "log" "os" "os/signal" "syscall" - "github.com/mehdihadeli/go-mediatr" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/docs" - productApi "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/api" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/commands" - creatingProductsDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/events" - gettingProductByIdDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/getting_product_by_id/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/getting_product_by_id/queries" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/repository" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/shared/behaviours" + "github.com/ehsandavari/go-mediator/examples/cqrs/docs" + productApi "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/api" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/commands" + creatingProductsDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/events" + gettingProductByIdDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/getting_product_by_id/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/getting_product_by_id/queries" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/repository" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/shared/behaviours" "github.com/labstack/echo/v4" echoSwagger "github.com/swaggo/echo-swagger" @@ -32,33 +32,33 @@ func main() { productRepository := repository.NewInMemoryProductRepository() ////////////////////////////////////////////////////////////////////////////////////////////// - // Register request handlers to the mediatr + // Register request handlers to the mediator createProductCommandHandler := commands.NewCreateProductCommandHandler(productRepository) getByIdQueryHandler := queries.NewGetProductByIdHandler(productRepository) - err := mediatr.RegisterRequestHandler[*commands.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](createProductCommandHandler) + err := mediator.RegisterRequestHandler[*commands.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](createProductCommandHandler) if err != nil { log.Fatal(err) } - err = mediatr.RegisterRequestHandler[*queries.GetProductByIdQuery, *gettingProductByIdDtos.GetProductByIdQueryResponse](getByIdQueryHandler) + err = mediator.RegisterRequestHandler[*queries.GetProductByIdQuery, *gettingProductByIdDtos.GetProductByIdQueryResponse](getByIdQueryHandler) if err != nil { log.Fatal(err) } ////////////////////////////////////////////////////////////////////////////////////////////// - // Register notification handlers to the mediatr + // Register notification handlers to the mediator notificationHandler := events.NewProductCreatedEventHandler() - err = mediatr.RegisterNotificationHandler[*events.ProductCreatedEvent](notificationHandler) + err = mediator.RegisterNotificationHandler[*events.ProductCreatedEvent](notificationHandler) if err != nil { log.Fatal(err) } ////////////////////////////////////////////////////////////////////////////////////////////// - // Register request handlers pipeline to the mediatr + // Register request handlers pipeline to the mediator loggerPipeline := &behaviours.RequestLoggerBehaviour{} - err = mediatr.RegisterRequestPipelineBehaviors(loggerPipeline) + err = mediator.RegisterRequestPipelineBehaviors(loggerPipeline) if err != nil { log.Fatal(err) } diff --git a/examples/cqrs/internal/products/api/products_controller.go b/examples/cqrs/internal/products/api/products_controller.go index 048a968..53c61f8 100644 --- a/examples/cqrs/internal/products/api/products_controller.go +++ b/examples/cqrs/internal/products/api/products_controller.go @@ -1,11 +1,11 @@ package api import ( - "github.com/mehdihadeli/go-mediatr" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/commands" - creatingProductsDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/dtos" - gettingProductByIdDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/getting_product_by_id/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/getting_product_by_id/queries" + "github.com/ehsandavari/go-mediator" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/commands" + creatingProductsDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/dtos" + gettingProductByIdDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/getting_product_by_id/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/getting_product_by_id/queries" "net/http" "github.com/go-playground/validator" @@ -43,7 +43,7 @@ func (pc *ProductsController) createProduct() echo.HandlerFunc { } command := commands.NewCreateProductCommand(request.Name, request.Description, request.Price) - result, err := mediatr.Send[*commands.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](ctx.Request().Context(), command) + result, err := mediator.Send[*commands.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](ctx.Request().Context(), command) if err != nil { return err @@ -76,7 +76,7 @@ func (pc *ProductsController) getProductByID() echo.HandlerFunc { return err } - queryResult, err := mediatr.Send[*queries.GetProductByIdQuery, *gettingProductByIdDtos.GetProductByIdQueryResponse](ctx.Request().Context(), query) + queryResult, err := mediator.Send[*queries.GetProductByIdQuery, *gettingProductByIdDtos.GetProductByIdQueryResponse](ctx.Request().Context(), query) if err != nil { return err diff --git a/examples/cqrs/internal/products/features/creating_product/commands/create_product_handler.go b/examples/cqrs/internal/products/features/creating_product/commands/create_product_handler.go index 5818bf0..da8c1d2 100644 --- a/examples/cqrs/internal/products/features/creating_product/commands/create_product_handler.go +++ b/examples/cqrs/internal/products/features/creating_product/commands/create_product_handler.go @@ -2,11 +2,11 @@ package commands import ( "context" - "github.com/mehdihadeli/go-mediatr" - creatingProductDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/creating_product/events" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/models" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/repository" + "github.com/ehsandavari/go-mediator" + creatingProductDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/creating_product/events" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/models" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/repository" ) type CreateProductCommandHandler struct { @@ -34,10 +34,10 @@ func (c *CreateProductCommandHandler) Handle(ctx context.Context, command *Creat response := &creatingProductDtos.CreateProductCommandResponse{ProductID: createdProduct.ProductID} - // Publish notification event to the mediatr for dispatching to the notification handlers + // Publish notification event to the mediator for dispatching to the notification handlers productCreatedEvent := events.NewProductCreatedEvent(createdProduct.ProductID, createdProduct.Name, createdProduct.Description, createdProduct.Price, createdProduct.CreatedAt) - err = mediatr.Publish[*events.ProductCreatedEvent](ctx, productCreatedEvent) + err = mediator.Publish[*events.ProductCreatedEvent](ctx, productCreatedEvent) if err != nil { return nil, err } diff --git a/examples/cqrs/internal/products/features/getting_product_by_id/dtos/get_product_by_id_response.go b/examples/cqrs/internal/products/features/getting_product_by_id/dtos/get_product_by_id_response.go index 61a6ca7..89acbf9 100644 --- a/examples/cqrs/internal/products/features/getting_product_by_id/dtos/get_product_by_id_response.go +++ b/examples/cqrs/internal/products/features/getting_product_by_id/dtos/get_product_by_id_response.go @@ -1,7 +1,7 @@ package dtos import ( - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/dtos" ) type GetProductByIdQueryResponse struct { diff --git a/examples/cqrs/internal/products/features/getting_product_by_id/queries/get_product_by_id_handler.go b/examples/cqrs/internal/products/features/getting_product_by_id/queries/get_product_by_id_handler.go index 824de1c..4677cd1 100644 --- a/examples/cqrs/internal/products/features/getting_product_by_id/queries/get_product_by_id_handler.go +++ b/examples/cqrs/internal/products/features/getting_product_by_id/queries/get_product_by_id_handler.go @@ -3,9 +3,9 @@ package queries import ( "context" "fmt" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products" - gettingProductByIdDtos "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/features/getting_product_by_id/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/repository" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products" + gettingProductByIdDtos "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/features/getting_product_by_id/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/repository" "github.com/pkg/errors" ) diff --git a/examples/cqrs/internal/products/mapper.go b/examples/cqrs/internal/products/mapper.go index 53710b2..b7e0b42 100644 --- a/examples/cqrs/internal/products/mapper.go +++ b/examples/cqrs/internal/products/mapper.go @@ -1,8 +1,8 @@ package products import ( - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/dtos" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/models" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/dtos" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/models" ) func MapProductToProductDto(product *models.Product) *dtos.ProductDto { diff --git a/examples/cqrs/internal/products/repository/inmemory_product_repository.go b/examples/cqrs/internal/products/repository/inmemory_product_repository.go index 6d0c824..5bfa228 100644 --- a/examples/cqrs/internal/products/repository/inmemory_product_repository.go +++ b/examples/cqrs/internal/products/repository/inmemory_product_repository.go @@ -2,7 +2,7 @@ package repository import ( "context" - "github.com/mehdihadeli/go-mediatr/examples/cqrs/internal/products/models" + "github.com/ehsandavari/go-mediator/examples/cqrs/internal/products/models" uuid "github.com/satori/go.uuid" ) diff --git a/examples/cqrs/internal/shared/behaviours/request_logger_behaviour.go b/examples/cqrs/internal/shared/behaviours/request_logger_behaviour.go index 6920cda..da2e630 100644 --- a/examples/cqrs/internal/shared/behaviours/request_logger_behaviour.go +++ b/examples/cqrs/internal/shared/behaviours/request_logger_behaviour.go @@ -2,14 +2,14 @@ package behaviours import ( "context" - "github.com/mehdihadeli/go-mediatr" + "github.com/ehsandavari/go-mediator" "log" ) type RequestLoggerBehaviour struct { } -func (r *RequestLoggerBehaviour) Handle(ctx context.Context, request interface{}, next mediatr.RequestHandlerFunc) (interface{}, error) { +func (r *RequestLoggerBehaviour) Handle(ctx context.Context, request interface{}, next mediator.RequestHandlerFunc) (interface{}, error) { log.Printf("logging some stuff before handling the request") response, err := next() diff --git a/go.mod b/go.mod index 5c2ba41..83d48da 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module github.com/mehdihadeli/go-mediatr +module github.com/ehsandavari/go-mediator -go 1.18 +go 1.20 require ( github.com/ahmetb/go-linq/v3 v3.2.0 diff --git a/mediatr.go b/mediatr.go index db93573..5a81b63 100644 --- a/mediatr.go +++ b/mediatr.go @@ -1,4 +1,4 @@ -package mediatr +package mediator import ( "context" @@ -9,11 +9,11 @@ import ( ) // RequestHandlerFunc is a continuation for the next task to execute in the pipeline -type RequestHandlerFunc func() (interface{}, error) +type RequestHandlerFunc func() (any, error) // PipelineBehavior is a Pipeline behavior for wrapping the inner handler. type PipelineBehavior interface { - Handle(ctx context.Context, request interface{}, next RequestHandlerFunc) (interface{}, error) + Handle(ctx context.Context, request any, next RequestHandlerFunc) (any, error) } type RequestHandler[TRequest any, TResponse any] interface { @@ -24,13 +24,13 @@ type NotificationHandler[TNotification any] interface { Handle(ctx context.Context, notification TNotification) error } -var requestHandlersRegistrations = map[reflect.Type]interface{}{} -var notificationHandlersRegistrations = map[reflect.Type][]interface{}{} -var pipelineBehaviours []interface{} = []interface{}{} +var requestHandlersRegistrations = map[reflect.Type]any{} +var notificationHandlersRegistrations = map[reflect.Type][]any{} +var pipelineBehaviours []any type Unit struct{} -// RegisterRequestHandler register the request handler to mediatr registry. +// RegisterRequestHandler register the request handler to mediator registry. func RegisterRequestHandler[TRequest any, TResponse any](handler RequestHandler[TRequest, TResponse]) error { var request TRequest requestType := reflect.TypeOf(request) @@ -46,7 +46,7 @@ func RegisterRequestHandler[TRequest any, TResponse any](handler RequestHandler[ return nil } -// RegisterRequestPipelineBehaviors register the request behaviors to mediatr registry. +// RegisterRequestPipelineBehaviors register the request behaviors to mediator registry. func RegisterRequestPipelineBehaviors(behaviours ...PipelineBehavior) error { for _, behavior := range behaviours { behaviorType := reflect.TypeOf(behavior) @@ -62,14 +62,14 @@ func RegisterRequestPipelineBehaviors(behaviours ...PipelineBehavior) error { return nil } -// RegisterNotificationHandler register the notification handler to mediatr registry. +// RegisterNotificationHandler register the notification handler to mediator registry. func RegisterNotificationHandler[TEvent any](handler NotificationHandler[TEvent]) error { var event TEvent eventType := reflect.TypeOf(event) handlers, exist := notificationHandlersRegistrations[eventType] if !exist { - notificationHandlersRegistrations[eventType] = []interface{}{handler} + notificationHandlersRegistrations[eventType] = []any{handler} return nil } @@ -78,7 +78,7 @@ func RegisterNotificationHandler[TEvent any](handler NotificationHandler[TEvent] return nil } -// RegisterNotificationHandlers register the notification handlers to mediatr registry. +// RegisterNotificationHandlers register the notification handlers to mediator registry. func RegisterNotificationHandlers[TEvent any](handlers ...NotificationHandler[TEvent]) error { if len(handlers) == 0 { return errors.New("no handlers provided") @@ -95,11 +95,11 @@ func RegisterNotificationHandlers[TEvent any](handlers ...NotificationHandler[TE } func ClearRequestRegistrations() { - requestHandlersRegistrations = map[reflect.Type]interface{}{} + requestHandlersRegistrations = map[reflect.Type]any{} } func ClearNotificationRegistrations() { - notificationHandlersRegistrations = map[reflect.Type][]interface{}{} + notificationHandlersRegistrations = map[reflect.Type][]any{} } // Send the request to its corresponding request handler. @@ -120,7 +120,7 @@ func Send[TRequest any, TResponse any](ctx context.Context, request TRequest) (T if len(pipelineBehaviours) > 0 { var reversPipes = reversOrder(pipelineBehaviours) - var lastHandler RequestHandlerFunc = func() (interface{}, error) { + var lastHandler RequestHandlerFunc = func() (any, error) { return handlerValue.Handle(ctx, request) } @@ -128,7 +128,7 @@ func Send[TRequest any, TResponse any](ctx context.Context, request TRequest) (T pipeValue := pipe nexValue := next - var handlerFunc RequestHandlerFunc = func() (interface{}, error) { + var handlerFunc RequestHandlerFunc = func() (any, error) { return pipeValue.Handle(ctx, request, nexValue) } @@ -180,8 +180,8 @@ func Publish[TNotification any](ctx context.Context, notification TNotification) return nil } -func reversOrder(values []interface{}) []interface{} { - var reverseValues []interface{} +func reversOrder(values []any) []any { + var reverseValues []any for i := len(values) - 1; i >= 0; i-- { reverseValues = append(reverseValues, values[i]) diff --git a/mediatr_benchmarks_test.go b/mediatr_benchmarks_test.go index 842c6f6..f0b0cc3 100644 --- a/mediatr_benchmarks_test.go +++ b/mediatr_benchmarks_test.go @@ -1,4 +1,4 @@ -package mediatr +package mediator import ( "context" @@ -8,7 +8,7 @@ import ( func Benchmark_Send(b *testing.B) { // because benchmark method will run multiple times, we need to reset the request handler registry before each run. - requestHandlersRegistrations = make(map[reflect.Type]interface{}) + requestHandlersRegistrations = make(map[reflect.Type]any) handler := &RequestTestHandler{} errRegister := RegisterRequestHandler[*RequestTest, *ResponseTest](handler) @@ -28,7 +28,7 @@ func Benchmark_Send(b *testing.B) { func Benchmark_Publish(b *testing.B) { // because benchmark method will run multiple times, we need to reset the notification handlers registry before each run. - notificationHandlersRegistrations = make(map[reflect.Type][]interface{}) + notificationHandlersRegistrations = make(map[reflect.Type][]any) handler := &NotificationTestHandler{} handler2 := &NotificationTestHandler4{} diff --git a/mediatr_test.go b/mediatr_test.go index f5ded62..546fb5b 100644 --- a/mediatr_test.go +++ b/mediatr_test.go @@ -1,4 +1,4 @@ -package mediatr +package mediator import ( "context" @@ -15,7 +15,7 @@ var testData []string func TestRunner(t *testing.T) { //https://pkg.go.dev/testing@master#hdr-Subtests_and_Sub_benchmarks t.Run("A=request-response", func(t *testing.T) { - test := MediatRTests{T: t} + test := mediatorTests{T: t} test.Test_RegisterRequestHandler_Should_Return_Error_If_Handler_Already_Registered_For_Request() test.Test_RegisterRequestHandler_Should_Register_All_Handlers_For_Different_Requests() test.Test_Send_Should_Throw_Error_If_No_Handler_Registered() @@ -25,7 +25,7 @@ func TestRunner(t *testing.T) { }) t.Run("B=notifications", func(t *testing.T) { - test := MediatRTests{T: t} + test := mediatorTests{T: t} test.Test_Publish_Should_Pass_If_No_Handler_Registered() test.Test_Publish_Should_Return_Error_If_Handler_Returns_Error() test.Test_Publish_Should_Dispatch_Notification_To_All_Handlers_Without_Any_Response_And_Error() @@ -33,21 +33,21 @@ func TestRunner(t *testing.T) { }) t.Run("C=pipeline-behaviours", func(t *testing.T) { - test := MediatRTests{T: t} + test := mediatorTests{T: t} test.Test_Register_Behaviours_Should_Register_Behaviours_In_The_Registry_Correctly() test.Test_Register_Duplicate_Behaviours_Should_Throw_Error() test.Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Response_With_Pipeline() }) } -type MediatRTests struct { +type mediatorTests struct { *testing.T } // Each request should have exactly one handler -func (t *MediatRTests) Test_RegisterRequestHandler_Should_Return_Error_If_Handler_Already_Registered_For_Request() { +func (t *mediatorTests) Test_RegisterRequestHandler_Should_Return_Error_If_Handler_Already_Registered_For_Request() { defer cleanup() - expectedErr := fmt.Sprintf("registered handler already exists in the registry for message %s", "*mediatr.RequestTest") + expectedErr := fmt.Sprintf("registered handler already exists in the registry for message %s", "*mediator.RequestTest") handler1 := &RequestTestHandler{} handler2 := &RequestTestHandler{} err1 := RegisterRequestHandler[*RequestTest, *ResponseTest](handler1) @@ -60,7 +60,7 @@ func (t *MediatRTests) Test_RegisterRequestHandler_Should_Return_Error_If_Handle assert.Equal(t, 1, count) } -func (t *MediatRTests) Test_RegisterRequestHandler_Should_Register_All_Handlers_For_Different_Requests() { +func (t *mediatorTests) Test_RegisterRequestHandler_Should_Register_All_Handlers_For_Different_Requests() { defer cleanup() handler1 := &RequestTestHandler{} handler2 := &RequestTestHandler2{} @@ -79,14 +79,14 @@ func (t *MediatRTests) Test_RegisterRequestHandler_Should_Register_All_Handlers_ assert.Equal(t, 2, count) } -func (t *MediatRTests) Test_Send_Should_Throw_Error_If_No_Handler_Registered() { +func (t *mediatorTests) Test_Send_Should_Throw_Error_If_No_Handler_Registered() { defer cleanup() expectedErr := fmt.Sprintf("no handler for request %T", &RequestTest{}) _, err := Send[*RequestTest, *ResponseTest](context.Background(), &RequestTest{Data: "test"}) assert.Containsf(t, err.Error(), expectedErr, "expected error containing %q, got %s", expectedErr, err) } -func (t *MediatRTests) Test_Send_Should_Return_Error_If_Handler_Returns_Error() { +func (t *mediatorTests) Test_Send_Should_Return_Error_If_Handler_Returns_Error() { defer cleanup() expectedErr := "error handling request" handler3 := &RequestTestHandler3{} @@ -98,7 +98,7 @@ func (t *MediatRTests) Test_Send_Should_Return_Error_If_Handler_Returns_Error() assert.Containsf(t, err.Error(), expectedErr, "expected error containing %q, got %s", expectedErr, err) } -func (t *MediatRTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Response_Without_Pipeline() { +func (t *mediatorTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Response_Without_Pipeline() { defer cleanup() handler := &RequestTestHandler{} errRegister := RegisterRequestHandler[*RequestTest, *ResponseTest](handler) @@ -112,7 +112,7 @@ func (t *MediatRTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Resp assert.Equal(t, "test", response.Data) } -func (t *MediatRTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Response_With_Pipeline() { +func (t *mediatorTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Response_With_Pipeline() { defer cleanup() pip1 := &PipelineBehaviourTest{} pip2 := &PipelineBehaviourTest2{} @@ -135,7 +135,7 @@ func (t *MediatRTests) Test_Send_Should_Dispatch_Request_To_Handler_And_Get_Resp assert.Contains(t, testData, "PipelineBehaviourTest2") } -func (t *MediatRTests) Test_RegisterNotificationHandler_Should_Register_Multiple_Handler_For_Notification() { +func (t *mediatorTests) Test_RegisterNotificationHandler_Should_Register_Multiple_Handler_For_Notification() { defer cleanup() handler1 := &NotificationTestHandler{} handler2 := &NotificationTestHandler{} @@ -153,7 +153,7 @@ func (t *MediatRTests) Test_RegisterNotificationHandler_Should_Register_Multiple assert.Equal(t, 2, count) } -func (t *MediatRTests) Test_RegisterNotificationHandlers_Should_Register_Multiple_Handler_For_Notification() { +func (t *mediatorTests) Test_RegisterNotificationHandlers_Should_Register_Multiple_Handler_For_Notification() { defer cleanup() handler1 := &NotificationTestHandler{} handler2 := &NotificationTestHandler{} @@ -169,13 +169,13 @@ func (t *MediatRTests) Test_RegisterNotificationHandlers_Should_Register_Multipl } // notifications could have zero or more handlers -func (t *MediatRTests) Test_Publish_Should_Pass_If_No_Handler_Registered() { +func (t *mediatorTests) Test_Publish_Should_Pass_If_No_Handler_Registered() { defer cleanup() err := Publish[*NotificationTest](context.Background(), &NotificationTest{}) assert.Nil(t, err) } -func (t *MediatRTests) Test_Publish_Should_Return_Error_If_Handler_Returns_Error() { +func (t *mediatorTests) Test_Publish_Should_Return_Error_If_Handler_Returns_Error() { defer cleanup() expectedErr := "error handling notification" handler1 := &NotificationTestHandler{} @@ -190,7 +190,7 @@ func (t *MediatRTests) Test_Publish_Should_Return_Error_If_Handler_Returns_Error assert.Containsf(t, err.Error(), expectedErr, "expected error containing %q, got %s", expectedErr, err) } -func (t *MediatRTests) Test_Publish_Should_Dispatch_Notification_To_All_Handlers_Without_Any_Response_And_Error() { +func (t *mediatorTests) Test_Publish_Should_Dispatch_Notification_To_All_Handlers_Without_Any_Response_And_Error() { defer cleanup() handler1 := &NotificationTestHandler{} handler2 := &NotificationTestHandler4{} @@ -205,7 +205,7 @@ func (t *MediatRTests) Test_Publish_Should_Dispatch_Notification_To_All_Handlers assert.True(t, notification.Processed) } -func (t *MediatRTests) Test_Register_Behaviours_Should_Register_Behaviours_In_The_Registry_Correctly() { +func (t *mediatorTests) Test_Register_Behaviours_Should_Register_Behaviours_In_The_Registry_Correctly() { defer cleanup() pip1 := &PipelineBehaviourTest{} pip2 := &PipelineBehaviourTest2{} @@ -219,7 +219,7 @@ func (t *MediatRTests) Test_Register_Behaviours_Should_Register_Behaviours_In_Th assert.Equal(t, 2, count) } -func (t *MediatRTests) Test_Register_Duplicate_Behaviours_Should_Throw_Error() { +func (t *mediatorTests) Test_Register_Duplicate_Behaviours_Should_Throw_Error() { defer cleanup() pip1 := &PipelineBehaviourTest{} pip2 := &PipelineBehaviourTest{} @@ -231,7 +231,7 @@ func (t *MediatRTests) Test_Register_Duplicate_Behaviours_Should_Throw_Error() { assert.Contains(t, err.Error(), "registered behavior already exists in the registry") } -func (t *MediatRTests) Test_Clear_Request_Registrations() { +func (t *mediatorTests) Test_Clear_Request_Registrations() { handler1 := &RequestTestHandler{} handler2 := &RequestTestHandler2{} err1 := RegisterRequestHandler[*RequestTest, *ResponseTest](handler1) @@ -244,14 +244,14 @@ func (t *MediatRTests) Test_Clear_Request_Registrations() { assert.Equal(t, 0, count) } -func (t *MediatRTests) Test_Clear_Notifications_Registrations() { +func (t *mediatorTests) Test_Clear_Notifications_Registrations() { handler1 := &NotificationTestHandler{} handler2 := &NotificationTestHandler4{} errRegister := RegisterNotificationHandlers[*NotificationTest](handler1, handler2) require.NoError(t, errRegister) ClearNotificationRegistrations() - + count := len(notificationHandlersRegistrations) assert.Equal(t, 0, count) } @@ -361,7 +361,7 @@ func (c *NotificationTestHandler4) Handle(ctx context.Context, notification *Not type PipelineBehaviourTest struct { } -func (c *PipelineBehaviourTest) Handle(ctx context.Context, request interface{}, next RequestHandlerFunc) (interface{}, error) { +func (c *PipelineBehaviourTest) Handle(ctx context.Context, request any, next RequestHandlerFunc) (any, error) { fmt.Println("PipelineBehaviourTest.Handled") testData = append(testData, "PipelineBehaviourTest") @@ -377,7 +377,7 @@ func (c *PipelineBehaviourTest) Handle(ctx context.Context, request interface{}, type PipelineBehaviourTest2 struct { } -func (c *PipelineBehaviourTest2) Handle(ctx context.Context, request interface{}, next RequestHandlerFunc) (interface{}, error) { +func (c *PipelineBehaviourTest2) Handle(ctx context.Context, request any, next RequestHandlerFunc) (any, error) { fmt.Println("PipelineBehaviourTest2.Handled") testData = append(testData, "PipelineBehaviourTest2") @@ -391,7 +391,7 @@ func (c *PipelineBehaviourTest2) Handle(ctx context.Context, request interface{} // ///////////////////////////////////////////////////////////////////////////////////////////// func cleanup() { - requestHandlersRegistrations = map[reflect.Type]interface{}{} - notificationHandlersRegistrations = map[reflect.Type][]interface{}{} - pipelineBehaviours = []interface{}{} + requestHandlersRegistrations = map[reflect.Type]any{} + notificationHandlersRegistrations = map[reflect.Type][]any{} + pipelineBehaviours = []any{} } diff --git a/readme.md b/readme.md index 961aa44..e65d404 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,12 @@
- go-mediatr + go-mediator
- build-status - go report + build-status + go report license - build-status - Coverage Status - build-status + build-status + Coverage Status + build-status
@@ -14,12 +14,12 @@ For decoupling some objects in a system we could use `Mediator` object as an interface, for decrease coupling between the objects. Mostly I uses this pattern when I use CQRS in my system. -There are some samples for using this package [here](./examples), also I used this packages widely in [this microservices sample](https://github.com/mehdihadeli/store-golang-microservices) +There are some samples for using this package [here](./examples), also I used this packages widely in [this microservices sample](https://github.com/ehsandavari/store-golang-microservices) ## 🧰 Installation ```bash -go get github.com/mehdihadeli/go-mediatr +go get github.com/ehsandavari/go-mediator ``` ## 🔥 Features @@ -27,10 +27,10 @@ go get github.com/mehdihadeli/go-mediatr ✅ Handling `Notification` message for delivering message to multiple handlers (Events) -✅ `Pipelenes Behaviours` for handling some cross cutting concerns before or after executing handlers +✅ `Pipelenes Behaviours` for handling some cross cutting concerns before or after executing handlers ## 🛡️ Strategies -Mediatr has two strategies for dispatching messages: +mediator has two strategies for dispatching messages: 1. `Request/Response` messages, dispatched to a `single handler`. 2. `Notification` messages, dispatched to all (multiple) `handlers` and they don't have any response. @@ -77,7 +77,7 @@ type GetProductByIdQueryResponse struct { #### Creating Request Handler -For handling our requests, we should create a `single request handler` for each request. Each handler should implement the `RequestHandler` interface. +For handling our requests, we should create a `single request handler` for each request. Each handler should implement the `RequestHandler` interface. ```go type RequestHandler[TRequest any, TResponse any] interface { Handle(ctx context.Context, request TRequest) (TResponse, error) @@ -148,25 +148,25 @@ func (c *GetProductByIdQueryHandler) Handle(ctx context.Context, query *GetProdu > Note: In the cases we don't need a response from our request handler, we can use `Unit` type, that actually is an empty struct:. -#### Registering Request Handler to the MediatR -Before `sending` or `dispatching` our requests, we should `register` our request handlers to the MediatR. +#### Registering Request Handler to the mediator +Before `sending` or `dispatching` our requests, we should `register` our request handlers to the mediator. -Here we register our request handlers (command handler and query handler) to the MediatR: +Here we register our request handlers (command handler and query handler) to the mediator: ```go -// Registering `createProductCommandHandler` request handler for `CreateProductCommand` request to the MediatR -mediatr.RegisterHandler[*creatingProduct.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](createProductCommandHandler) +// Registering `createProductCommandHandler` request handler for `CreateProductCommand` request to the mediator +mediator.RegisterHandler[*creatingProduct.CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](createProductCommandHandler) -// Registering `getProductByIdQueryHandler` request handler for `GetProductByIdQuery` request to the MediatR -mediatr.RegisterHandler[*gettingProduct.GetProductByIdQuery, *gettingProductDtos.GetProdctByIdQueryResponse](getProductByIdQueryHandler) +// Registering `getProductByIdQueryHandler` request handler for `GetProductByIdQuery` request to the mediator +mediator.RegisterHandler[*gettingProduct.GetProductByIdQuery, *gettingProductDtos.GetProdctByIdQueryResponse](getProductByIdQueryHandler) ``` -#### Sending Request to the MediatR +#### Sending Request to the mediator Finally, send a message through the mediator. -Here we send our requests to the MediatR for dispatching them to the request handlers (command handler and query handler): +Here we send our requests to the mediator for dispatching them to the request handlers (command handler and query handler): ``` go -// Sending `CreateProductCommand` request to mediatr for dispatching to the `CreateProductCommandHandler` request handler +// Sending `CreateProductCommand` request to mediator for dispatching to the `CreateProductCommandHandler` request handler command := &CreateProductCommand{ ProductID: uuid.NewV4(), Name: request.name, @@ -175,16 +175,16 @@ command := &CreateProductCommand{ CreatedAt: time.Now(), } -mediatr.Send[*CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](ctx, command) +mediator.Send[*CreateProductCommand, *creatingProductsDtos.CreateProductCommandResponse](ctx, command) ``` ```go -// Sending `GetProductByIdQuery` request to mediatr for dispatching to the `GetProductByIdQueryHandler` request handler +// Sending `GetProductByIdQuery` request to mediator for dispatching to the `GetProductByIdQueryHandler` request handler query := &GetProdctByIdQuery{ ProductID: uuid.NewV4() } -mediatr.Send[*GetProductByIdQuery, *gettingProductsDtos.GetProductByIdQueryResponse](ctx, query) +mediator.Send[*GetProductByIdQuery, *gettingProductsDtos.GetProductByIdQueryResponse](ctx, query) ``` ### Notification Strategy @@ -240,24 +240,24 @@ func (c *ProductCreatedEventHandler2) Handle(ctx context.Context, event *Product } ``` -#### Registering Notification Handlers to the MediatR -Before `publishing` our notifications, we should `register` our notification handlers to the MediatR. +#### Registering Notification Handlers to the mediator +Before `publishing` our notifications, we should `register` our notification handlers to the mediator. -Here we register our notification handlers to the MediatR: +Here we register our notification handlers to the mediator: ```go -// Registering `notificationHandler1`, `notificationHandler2` notification handler for `ProductCreatedEvent` notification event to the MediatR +// Registering `notificationHandler1`, `notificationHandler2` notification handler for `ProductCreatedEvent` notification event to the mediator notificationHandler1 := &ProductCreatedEventHandler1{} notificationHandler2 := &ProductCreatedEventHandler2{} -mediatr.RegisterNotificationHandlers[*events.ProductCreatedEvent](notificationHandler1, notificationHandler2) +mediator.RegisterNotificationHandlers[*events.ProductCreatedEvent](notificationHandler1, notificationHandler2) ``` -#### Publishing Notification to the MediatR +#### Publishing Notification to the mediator Finally, publish a notification event through the mediator. -Here we publish our notification to the MediatR for dispatching them to the notification handlers: +Here we publish our notification to the mediator for dispatching them to the notification handlers: ``` go -// Publishing `ProductCreatedEvent` notification to mediatr for dispatching to the `ProductCreatedEventHandler1`, `ProductCreatedEventHandler2` notification handlers +// Publishing `ProductCreatedEvent` notification to mediator for dispatching to the `ProductCreatedEventHandler1`, `ProductCreatedEventHandler2` notification handlers productCreatedEvent := &ProductCreatedEvent { ProductID: createdProduct.ProductID, Name: createdProduct.Name, @@ -266,13 +266,13 @@ productCreatedEvent := &ProductCreatedEvent { Description: createdProduct.Description, } -mediatr.Publish[*events.ProductCreatedEvent](ctx, productCreatedEvent) +mediator.Publish[*events.ProductCreatedEvent](ctx, productCreatedEvent) ``` ## ⚒️ Using Pipeline Behaviors Sometimes we need to add some cross-cutting concerns before after running our request handlers like logging, metrics, circuit breaker, retry, etc. In this case we can use `PipelineBehavior`. It is actually is like a middleware or [decorator pattern](https://refactoring.guru/design-patterns/decorator). -These behaviors will execute before or after running our request handlers with calling `Send` method for a request on the mediatr. +These behaviors will execute before or after running our request handlers with calling `Send` method for a request on the mediator. ### Creating Pipeline Behavior For creating a pipeline behaviour we should implement the `PipelineBehavior` interface: @@ -282,7 +282,7 @@ type PipelineBehavior interface { Handle(ctx context.Context, request interface{}, next RequestHandlerFunc) (interface{}, error) } ``` -The `request` parameter is the request object passed in through `Send` method of mediatr, while the `next` parameter is a continuation for the next action in the behavior chain and its type is `RequestHandlerFunc`. +The `request` parameter is the request object passed in through `Send` method of mediator, while the `next` parameter is a continuation for the next action in the behavior chain and its type is `RequestHandlerFunc`. Here is an example of a pipeline behavior: @@ -290,7 +290,7 @@ Here is an example of a pipeline behavior: type RequestLoggerBehaviour struct { } -func (r *RequestLoggerBehaviour) Handle(ctx context.Context, request interface{}, next mediatr.RequestHandlerFunc) (interface{}, error) { +func (r *RequestLoggerBehaviour) Handle(ctx context.Context, request interface{}, next mediator.RequestHandlerFunc) (interface{}, error) { log.Printf("logging some stuff before handling the request") response, err := next() @@ -305,13 +305,11 @@ func (r *RequestLoggerBehaviour) Handle(ctx context.Context, request interface{} ``` In our defined behavior, we need to call `next` parameter that call next action in the behavior chain, if there aren't any other behaviours `next` will call our `actual request handler` and return the response. We can do something before of after of calling next action in the behavior chain. -### Registering Pipeline Behavior to the MediatR +### Registering Pipeline Behavior to the mediator -For registering our pipeline behavior to the MediatR, we should use `RegisterPipelineBehaviors` method: +For registering our pipeline behavior to the mediator, we should use `RegisterPipelineBehaviors` method: ```go loggerPipeline := &behaviours.RequestLoggerBehaviour{} -err = mediatr.RegisterRequestPipelineBehaviors(loggerPipeline) -``` - - +err = mediator.RegisterRequestPipelineBehaviors(loggerPipeline) +``` \ No newline at end of file