Go-MediatR icon indicating copy to clipboard operation
Go-MediatR copied to clipboard

[Help] Go-MediatR with Fx

Open tomflenner opened this issue 9 months ago • 2 comments

Hi,

Do you have any examples of Go-MediatR integration with uber-fx? 👀

I tried something like that, but I'm not sure if it's the best way (it's a quick fork of your example) :

package core

import (
	"context"
	"log"

	dtos "example.com/fxdemo/core/dtos"
	interfaces "example.com/fxdemo/core/interfaces"
	mappers "example.com/fxdemo/core/mappers"
	"github.com/mehdihadeli/go-mediatr"
	"go.uber.org/fx"
)

// Command Handler
type CreateProductCommandHandler struct {
	productRepository interfaces.ProductRepository
}

func NewCreateProductCommandHandler(productRepository interfaces.ProductRepository) *CreateProductCommandHandler {
	return &CreateProductCommandHandler{productRepository: productRepository}
}

func (c *CreateProductCommandHandler) Handle(ctx context.Context, command *CreateProductCommand) (*CreateProductCommandResponse, error) {
	productDto := &dtos.ProductDto{
		Name:        command.Name,
		Description: command.Description,
		Price:       command.Price,
	}

	product := mappers.MapProductDtoToProduct(productDto)

	createdProduct, err := c.productRepository.AddProduct(product)

	if err != nil {
		return nil, err
	}

	response := &CreateProductCommandResponse{ProductUUID: createdProduct.ProductUUID}

	return response, nil
}

func registerHandler(createCommandHandler *CreateProductCommandHandler) {
	err := mediatr.RegisterRequestHandler[*CreateProductCommand, *CreateProductCommandResponse](createCommandHandler)
	if err != nil {
		log.Fatal(err)
	}
}

var CreateProductModule = fx.Options(
	fx.Provide(NewCreateProductCommandHandler),
	fx.Invoke(registerHandler))

with a main fx.go for my layer :

package core

import (
	core "example.com/fxdemo/core/commands/product/create"
	"go.uber.org/fx"
)

var Module = fx.Options(
	core.CreateProductModule,
)

To be able to use like this in my endpoint :

package api

import (
	"fmt"

	handler "example.com/fxdemo/api/handler"
	core "example.com/fxdemo/core/commands/product/create"
	"github.com/gin-gonic/gin"
	"github.com/mehdihadeli/go-mediatr"
	"go.uber.org/fx"
)

func registerProductRoutes(handler *handler.Handler) {
	v1 := handler.Gin.Group("/api/v1")
	{
		product := v1.Group("product")
		{
			product.POST("", func(c *gin.Context) {
				command := core.NewCreateProductCommand("Product test", "Description test", 10)

				result, err := mediatr.Send[*core.CreateProductCommand, *core.CreateProductCommandResponse](c, command)

				if err != nil {
					message := fmt.Errorf(err.Error())
					fmt.Println(message)
				}

				fmt.Println(result)

				c.JSON(200, gin.H{"message": "Post PRODUCT OK"})
			})
		}
	}
}

var ProductControllerModule = fx.Options(fx.Invoke(registerProductRoutes))

Thansk in advance ! 🙏🏻

Feel free to give any feedback on my code 👍🏻

tomflenner avatar Nov 15 '23 21:11 tomflenner