Skip to content

Commit

Permalink
refactor: add validate to command/query level (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: Alan-maqing <maqing@dongyu-technology.com>
Fix #7
  • Loading branch information
Alan-MQ committed Aug 31, 2023
1 parent e17d929 commit be8df31
Show file tree
Hide file tree
Showing 28 changed files with 181 additions and 193 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.20.4
go-version: 1.20.x
id: go

- name: Cache go modules
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
# https://github.com/testcontainers/testcontainers-go/issues/1359
- uses: actions/setup-go@v3
with:
go-version: 1.20.4
go-version: 1.20.x

- name: Get dependencies
run: make install-dependencies
Expand Down
5 changes: 2 additions & 3 deletions internal/services/catalog_read_service/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
emperror.dev/errors v0.8.1
github.com/brianvoe/gofakeit/v6 v6.19.0
github.com/gavv/httpexpect/v2 v2.3.1
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible
github.com/go-playground/validator v9.31.0+incompatible
github.com/go-redis/redis/v8 v8.11.5
github.com/labstack/echo/v4 v4.10.2
Expand All @@ -29,7 +30,6 @@ require (
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/EventStore/EventStore-Client-Go v1.0.2 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
Expand All @@ -41,6 +41,7 @@ require (
github.com/ahmetb/go-linq/v3 v3.2.0 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/caarlos0/env/v8 v8.0.0 // indirect
Expand Down Expand Up @@ -120,7 +121,6 @@ require (
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down Expand Up @@ -182,7 +182,6 @@ require (
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
Expand Down
63 changes: 14 additions & 49 deletions internal/services/catalog_read_service/go.sum

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package commands
import (
"time"

"github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/validator"
validation "github.com/go-ozzo/ozzo-validation"

uuid "github.com/satori/go.uuid"
)

Expand Down Expand Up @@ -32,10 +33,19 @@ func NewCreateProduct(
Price: price,
CreatedAt: createdAt,
}
err := validator.Validate(command)
err := command.Validate()
if err != nil {
return nil, err
}

return command, nil
}

func (p *CreateProduct) Validate() error {
return validation.ValidateStruct(p, validation.Field(&p.Id, validation.Required),
validation.Field(&p.ProductId, validation.Required),
validation.Field(&p.Name, validation.Required, validation.Length(3, 250)),
validation.Field(&p.Description, validation.Required, validation.Length(3, 500)),
validation.Field(&p.Price, validation.Required),
validation.Field(&p.CreatedAt, validation.Required))
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
package commands

import uuid "github.com/satori/go.uuid"
import (
validation "github.com/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
uuid "github.com/satori/go.uuid"
)

type DeleteProduct struct {
ProductId uuid.UUID `validate:"required"`
}

func NewDeleteProduct(productId uuid.UUID) *DeleteProduct {
return &DeleteProduct{ProductId: productId}
func NewDeleteProduct(productId uuid.UUID) (*DeleteProduct, error) {
delProduct := &DeleteProduct{ProductId: productId}
if err := delProduct.Validate(); err != nil {
return nil, err
}
return delProduct, nil
}

func (p *DeleteProduct) Validate() error {
return validation.ValidateStruct(p,
validation.Field(&p.ProductId, validation.Required, is.UUIDv4))
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ func (c *productDeletedConsumer) Handle(
return err
}

command := commands.NewDeleteProduct(productUUID)
if err := c.validator.StructCtx(ctx, command); err != nil {
command, err := commands.NewDeleteProduct(productUUID)
if err != nil {
validationErr := customErrors.NewValidationErrorWrap(
err,
"[productDeletedConsumer_Handle.StructCtx] command validation failed",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc {
return badRequestErr
}

query := queries.NewGetProductById(request.Id)

if err := ep.Validator.StructCtx(ctx, query); err != nil {
query, err := queries.NewGetProductById(request.Id)
if err != nil {
validationErr := customErrors.NewValidationErrorWrap(
err,
"[getProductByIdEndpoint_handler.StructCtx] query validation failed",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package queries

import (
validation "github.com/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
uuid "github.com/satori/go.uuid"
)

type GetProductById struct {
Id uuid.UUID `validate:"required"`
}

func NewGetProductById(id uuid.UUID) *GetProductById {
return &GetProductById{Id: id}
func NewGetProductById(id uuid.UUID) (*GetProductById, error) {
product := &GetProductById{Id: id}
if err := product.Validate(); err != nil {
return nil, err
}
return product, nil
}

func (p *GetProductById) Validate() error {
return validation.ValidateStruct(p, validation.Field(&p.Id, validation.Required, is.UUIDv4))
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc {
ListQuery: request.ListQuery,
}

if err := ep.Validator.StructCtx(ctx, query); err != nil {
if err := query.Validate(); err != nil {
validationErr := customErrors.NewValidationErrorWrap(
err,
"[searchProductsEndpoint_handler.StructCtx] query validation failed",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package queries

import "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils"
import (
validation "github.com/go-ozzo/ozzo-validation"
"github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils"
)

type SearchProducts struct {
SearchText string `validate:"required"`
*utils.ListQuery
}

func (s *SearchProducts) Validate() error {
return validation.ValidateStruct(s, validation.Field(&s.SearchText, validation.Required))
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package commands
import (
"time"

"github.com/go-ozzo/ozzo-validation/is"

validation "github.com/go-ozzo/ozzo-validation"

uuid "github.com/satori/go.uuid"
)

Expand All @@ -14,12 +18,25 @@ type UpdateProduct struct {
UpdatedAt time.Time `validate:"required"`
}

func NewUpdateProduct(productId uuid.UUID, name string, description string, price float64) *UpdateProduct {
return &UpdateProduct{
func NewUpdateProduct(productId uuid.UUID, name string, description string, price float64) (*UpdateProduct, error) {
product := &UpdateProduct{
ProductId: productId,
Name: name,
Description: description,
Price: price,
UpdatedAt: time.Now(),
}
if err := product.Validate(); err != nil {
return nil, err
}
return product, nil
}

func (p *UpdateProduct) Validate() error {
return validation.ValidateStruct(p, validation.Field(&p.ProductId, validation.Required, is.UUIDv4),
validation.Field(&p.Name, validation.Required, validation.Length(0, 255)),
validation.Field(&p.Description, validation.Required, validation.Length(0, 5000)),
validation.Field(&p.Price, validation.Required, validation.Min(0.0)),
validation.Field(&p.UpdatedAt, validation.Required),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ func (c *productUpdatedConsumer) Handle(
return err
}

command := commands.NewUpdateProduct(
command, err := commands.NewUpdateProduct(
productUUID,
message.Name,
message.Description,
message.Price,
)
if err := c.validator.StructCtx(ctx, command); err != nil {
if err != nil {
validationErr := customErrors.NewValidationErrorWrap(
err,
"[updateProductConsumer_Consume.StructCtx] command validation failed",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ func (c *deleteProductIntegrationTests) Test_Delete_Product_Command_Handler() {
productId, err := uuid.FromString(c.Items[0].ProductId)
c.NoError(err)

command := commands.NewDeleteProduct(productId)
command, err := commands.NewDeleteProduct(productId)
c.NoError(err)
result, err := mediatr.Send[*commands.DeleteProduct, *mediatr.Unit](
context.Background(),
command,
Expand All @@ -41,3 +42,9 @@ func (c *deleteProductIntegrationTests) Test_Delete_Product_Command_Handler() {
c.NoError(err)
c.NotNil(result)
}

func (c *deleteProductIntegrationTests) Test_Delete_Product_Command_Handler_Should_Return_Error_Not_Valid_UUID() {
command, err := commands.NewDeleteProduct(uuid.UUID{})
c.Assert().Nil(command)
c.Require().Error(err)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ func (c *getProductByIdIntegrationTests) Test_Get_Product_By_Id_Query_Handler()
ctx := context.Background()
id, err := uuid.FromString(c.Items[0].Id)
c.Require().NoError(err)

query := queries.NewGetProductById(id)
query, err := queries.NewGetProductById(id)
c.Require().NoError(err)
result, err := mediatr.Send[*queries.GetProductById, *dtos.GetProductByIdResponseDto](
ctx,
query,
Expand All @@ -43,3 +43,9 @@ func (c *getProductByIdIntegrationTests) Test_Get_Product_By_Id_Query_Handler()
c.NotNil(result.Product)
c.Equal(result.Product.Id, id.String())
}

func (c *getProductByIdIntegrationTests) Test_Should_Return_Error_For_Not_Valid_ID() {
query, err := queries.NewGetProductById(uuid.UUID{})
c.Assert().Nil(query)
c.Require().Error(err)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ func (c *updateProductIntegrationTests) Test_Update_Product_Command_Handler() {
productId, err := uuid.FromString(c.Items[0].ProductId)
c.Require().NoError(err)

command := commands.NewUpdateProduct(
command, err := commands.NewUpdateProduct(
productId,
gofakeit.Name(),
gofakeit.AdjectiveDescriptive(),
gofakeit.Price(150, 6000),
)
c.Require().NoError(err)

result, err := mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command)
c.Require().NoError(err)
Expand Down
5 changes: 2 additions & 3 deletions internal/services/catalog_write_service/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
emperror.dev/errors v0.8.1
github.com/brianvoe/gofakeit/v6 v6.18.0
github.com/gavv/httpexpect/v2 v2.3.1
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible
github.com/go-playground/validator v9.31.0+incompatible
github.com/goccy/go-json v0.10.2
github.com/iancoleman/strcase v0.2.0
Expand All @@ -33,7 +34,6 @@ require (
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/ClickHouse/ch-go v0.55.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.9.1 // indirect
Expand All @@ -48,6 +48,7 @@ require (
github.com/ajg/form v1.5.1 // indirect
github.com/alexflint/go-filemutex v1.1.0 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/caarlos0/env/v8 v8.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
Expand Down Expand Up @@ -194,7 +195,6 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/prometheus/client_golang v1.15.1 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
Expand All @@ -204,7 +204,6 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
google.golang.org/protobuf v1.30.0
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
Loading

0 comments on commit be8df31

Please sign in to comment.